home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / morse / superior.sh < prev    next >
Linux/UNIX/POSIX Shell Script  |  1996-06-25  |  92KB  |  4,062 lines

  1. #! /bin/sh
  2. # This is a shell archive.  Remove anything before this line, then unpack
  3. # it by saving it into a file and typing "sh file".  To overwrite existing
  4. # files, type "sh file -c".  You can also feed this as standard input via
  5. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  6. # will see the following message at the end:
  7. #        "End of shell archive."
  8. # Contents:  Makefile QSO.c alarm.c alarm.h beep.h beepHP.c beepSun.c
  9. #   beepX11.c morse.c
  10. # Wrapped by joe@montebello on Sat Nov 28 03:13:57 1992
  11. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  12. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  13.   echo shar: Will not clobber existing file \"'Makefile'\"
  14. else
  15. echo shar: Extracting \"'Makefile'\" \(1101 characters\)
  16. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  17. X# Select your audio output device.  Current choices are:
  18. X#   Sun:   Sun workstation with audio hardware.
  19. X#   HP:    HP9000s700 with audio hardware.
  20. X#   X11:   The X11 window system.
  21. X# Adding a new device is as simple as creating a new implementation of the
  22. X# beep.h interface.  See beep*.c for examples.  Please send any additions
  23. X# to the authors.
  24. X#
  25. XDEVICE = X11
  26. X
  27. X# For termio a la System V, add -DUSG to DEFINES.
  28. X# For alternate random number generator, add either -DUSELRAND for lrand48(),
  29. X#   or -DUSERAND for (ugh) rand().
  30. XDEFINES =
  31. X
  32. X
  33. XCFLAGS  = -O ${DEFINES}
  34. X
  35. X
  36. Xmorse:    morse${DEVICE}
  37. X    rm -f $@
  38. X    ln morse${DEVICE} $@
  39. X
  40. XmorseSun:    morse.o beepSun.o
  41. X    cc -o $@ morse.o beepSun.o -L/usr/demo/SOUND -laudio -lm
  42. X
  43. XmorseHP:    morse.o beepHP.o alarm.o
  44. X    cc -o $@ morse.o beepHP.o alarm.o -lm
  45. X
  46. XmorseX11:    morse.o beepX11.o alarm.o
  47. X    cc -o $@ morse.o beepX11.o alarm.o -lX11
  48. X
  49. XQSO:    QSO.o
  50. X    cc -o $@ QSO.o
  51. X
  52. Xtest:
  53. X    QSO | morse -l -e
  54. X
  55. Xclean:
  56. X    rm -f *.o morseSun morseHP morseX11 QSO
  57. X
  58. Xsqueakyclean:    clean
  59. X    rm -f morse
  60. X
  61. X
  62. Xmorse.o:    beep.h
  63. XbeepSun.o:    beep.h
  64. XbeepHP.o:    beep.h alarm.h
  65. XbeepX11.o:    beep.h alarm.h
  66. Xalarm.o:    alarm.h
  67. END_OF_FILE
  68. if test 1101 -ne `wc -c <'Makefile'`; then
  69.     echo shar: \"'Makefile'\" unpacked with wrong size!
  70. fi
  71. # end of 'Makefile'
  72. fi
  73. if test -f 'QSO.c' -a "${1}" != "-c" ; then 
  74.   echo shar: Will not clobber existing file \"'QSO.c'\"
  75. else
  76. echo shar: Extracting \"'QSO.c'\" \(27050 characters\)
  77. sed "s/^X//" >'QSO.c' <<'END_OF_FILE'
  78. X/*
  79. X * Return-Path: <pjd@cadillac.siemens.com>
  80. X * Received: from cadillac.siemens.com by montebello.soest.hawaii.edu (4.1/montebello-MX-1.9)
  81. X *     id AA01487; Mon, 10 Aug 92 03:21:41 HST
  82. X * Received: from kevin.siemens.com by cadillac.siemens.com (4.1/SMI-4.0)
  83. X *     id AA25847; Mon, 10 Aug 92 09:21:37 EDT
  84. X * Date: Mon, 10 Aug 92 09:21:37 EDT
  85. X * From: pjd@cadillac.siemens.com (paul j. drongowski)
  86. X * Message-Id: <9208101321.AA25847@cadillac.siemens.com>
  87. X * To: joe@montebello.soest.hawaii.edu
  88. X * Status: RO
  89. X *
  90. X * This copy is slightly hacked by Joe Dellinger, August 1992
  91. X * And some more... November 1992
  92. X */
  93. X
  94. X/*
  95. X * Generate QSO
  96. X */
  97. X
  98. X/*
  99. X * Author:  Paul J. Drongowski / N2OQT
  100. X * Address: 1 Allen Court
  101. X *          Plainsboro, New Jersey 08536
  102. X * Date:    10 October 1991
  103. X *
  104. X * Copyright (c) 1991 Paul J. Drongowski
  105. X */
  106. X
  107. X/*
  108. X * When run, this program generates a single QSO. The form of the
  109. X * QSO is similar to QSO`s one would expect to hear at a code test.
  110. X * It begins with a series of V's (commented out in this version),
  111. X * callsigns of the receiver and
  112. X * sender, followed by a few sentences about weather, name,
  113. X * occupation, etc. The QSO ends with the callsigns of the receiver
  114. X * and sender.
  115. X *
  116. X * All output is produced using "printf." This should make the
  117. X * program easy to port. Output can be piped into another program
  118. X * such as sparc-morse on the Sun or it can be redirected into
  119. X * a file (without viewing the contents of course!)
  120. X *
  121. X * The program design is similar to a "random poetry generator"
  122. X * or "mad-libs." Each QSO form is generated by its own C function,
  123. X * such as "PutForm1." Each function calls other C functions to
  124. X * produce the sentences in the QSO. The sentence forms are
  125. X * selected somewhat randomly as well as any blanks to be filled.
  126. X * Words and phrases are selected from several lists such as
  127. X * "Transceiver," "Antenna," "Job," etc. Sometimes this scheme is
  128. X * clever as in the formation of city names. Sometimes it is
  129. X * stupidly simple-minded and grammatical agreement is lost.
  130. X * By the way, the callsigns are real and were picked from
  131. X * rec.radio.amateur.misc on USENET.
  132. X *
  133. X * The program was constructed in C for Sun workstations. It uses
  134. X * the library function "drand48" in function "Roll" to produce
  135. X * pseudo-random numbers. The library function "srand48" and "time"
  136. X * in "main" are used to set the pseudo-random number seed.
  137. X *
  138. X * Known problems and caveats? Hey, it`s software! All Morse
  139. X * training programs handle the procedural signs (e.g., AR, SK)
  140. X * differently. The function "PutQSO" currently prints "+ @"
  141. X * for the AR and SK at the end of the QSO. These may be ignored,
  142. X * mapped into something else, or just plain cause your training
  143. X * program to roll over and play dead. I don`t know. This is a
  144. X * cheap hack.
  145. X *
  146. X * And speaking of cheap... The program will not generate all
  147. X * characters and pro-signs that are found on an "official" code
  148. X * test. This program is for practice only and should be supplemented
  149. X * with lots of random code.
  150. X *
  151. X * Please note that I retain the copyright
  152. X * to this program. You may use it for any non-commercial purposes.
  153. X * This is roughly equivalent to "fair use."
  154. X *
  155. X * Always have fun!
  156. X */
  157. X
  158. X
  159. X#include <sys/types.h>
  160. X#include <sys/time.h>
  161. X
  162. Xint NXCVR ;
  163. Xchar *Transceiver[] =
  164. X
  165. X  {
  166. X  "Collins 75S=3",
  167. X  "Collins KWM=2",
  168. X  "Drake TR3",
  169. X  "Drake TR4",
  170. X  "Drake T=4XB",
  171. X  "Eico 753",
  172. X  "Hallicrafters SR150",
  173. X  "Hallicrafters SR160",
  174. X  "Hallicrafters SR400",
  175. X  "Hallicrafters SR500",
  176. X  "Hallicrafters SR2000",
  177. X  "Heathkit DX=660B",
  178. X  "Heathkit HG=10B",
  179. X  "Heathkit HR=10",
  180. X  "Heathkit HW12",
  181. X  "Heathkit HW22",
  182. X  "Heathkit HW32",
  183. X  "Heathkit HW12A",
  184. X  "Heathkit HW22A",
  185. X  "Heathkit HW32A",
  186. X  "Heathkit HW100",
  187. X  "Heathkit SB100",
  188. X  "Icom IC=275",
  189. X  "Icom IC=475",
  190. X  "Icom IC=575",
  191. X  "Icom IC=725",
  192. X  "Icom IC=726",
  193. X  "Icom IC=730",
  194. X  "Icom IC=735",
  195. X  "Icom IC=751",
  196. X  "Icom IC=765",
  197. X  "Icom IC=781",
  198. X  "Icom IC=1275",
  199. X  "Kenwood TS=77",
  200. X  "Kenwood TS=140",
  201. X  "Kenwood TS=440",
  202. X  "Kenwood TS=680",
  203. X  "Kenwood TS=711",
  204. X  "Kenwood TS=850",
  205. X  "Kenwood TR=450",
  206. X  "Kenwood TR=751",
  207. X  "Kenwood TR=850",
  208. X  "Kenwood TR=851",
  209. X  "National NCX3",
  210. X  "National NCX5",
  211. X  "National NCL 200",
  212. X  "Radio Shack HTX=100",
  213. X  "RS HTX=100",
  214. X  "Swan 120",
  215. X  "Swan 140",
  216. X  "Swan 180",
  217. X  "Swan 240",
  218. X  "Swan 350",
  219. X  "Ten Tec 585",
  220. X  "Ten Tec 562",
  221. X  "Ten Tec Delta",
  222. X  "Ten Tec Argonaut",
  223. X  "Ten Tec Omni",
  224. X  "Yaesu FT=101",
  225. X  "Yaesu FT=736",
  226. X  "Yaesu FT=747",
  227. X  "Yaesu FT=757",
  228. X  "Yaesu FT=767",
  229. X  "Yaesu FT=990",
  230. X  "Yaesu FT=1000",
  231. X  "Homebrew",
  232. X  0
  233. X  } ;
  234. X
  235. Xint NANTENNA ;
  236. Xchar *Antenna[] =
  237. X
  238. X  {
  239. X  "beam",
  240. X  "delta loop",
  241. X  "dipole",
  242. X  "doublet zepp",
  243. X  "half wave dipole",
  244. X  "inverted V",
  245. X  "whip",
  246. X  "delta loop",
  247. X  "parasitic beam",
  248. X  "log periodic",
  249. X  "quad loop",
  250. X  "quad vertical",
  251. X  "quagi",
  252. X  "quarter wave vertical",
  253. X  "rhombic",
  254. X  "long=wire",
  255. X  "ground=plane",
  256. X  "trap doublet",
  257. X  "yagi",
  258. X  "zepp",
  259. X  "monobander",
  260. X  "tribander",
  261. X  "symmetrical delta loop",
  262. X  "3 element beam",
  263. X  "5 band vertical",
  264. X  "5 element loop",
  265. X  "10 meter dipole",
  266. X  "10 meter whip",
  267. X  "7 band beam",
  268. X  0
  269. X  } ;
  270. X
  271. Xint NUPFEET ;
  272. Xchar *UpFeet[] =
  273. X
  274. X  {
  275. X  "10", "15", "20", "25", "30", "35", "40", "45",
  276. X  "50", "55", "60", "65", "70", "75", "80", "85",
  277. X  "90", "95", "100",
  278. X  0
  279. X  } ;
  280. X
  281. Xint NWX1 ;
  282. Xchar *Weather1[] =
  283. X
  284. X  {
  285. X  "sunny",
  286. X  "rain",
  287. X  "freezing rain",
  288. X  "sleet",
  289. X  "snow",
  290. X  "cloudy",
  291. X  "partly cloudy",
  292. X  "partly sunny",
  293. X  "clear",
  294. X  0
  295. X  } ;
  296. X
  297. Xint NWX2 ;
  298. Xchar *Weather2[] =
  299. X
  300. X  {
  301. X  "cold and windy",
  302. X  "raining",
  303. X  "snowing",
  304. X  "sunny",
  305. X  "hot",
  306. X  "windy and warm",
  307. X  "cloudy",
  308. X  "drizzling",
  309. X  "foggy",
  310. X  "wet/foggy",
  311. X  "fog/drizzle",
  312. X  "hot/muggy",
  313. X  "hot/dry",
  314. X  "cool/windy",
  315. X  "smoggy",
  316. X  "hot/smoggy",
  317. X  "cold/dry",
  318. X  "hot/humid",
  319. X  "warm",
  320. X  "windy",
  321. X  "very hot",
  322. X  "very cold",
  323. X  "very windy",
  324. X  "wet",
  325. X  "wet/windy",
  326. X  "humid",
  327. X  "hot and humid",
  328. X  0
  329. X  } ;
  330. X
  331. Xint NPOWER ;
  332. Xchar *Power[] =
  333. X
  334. X  {
  335. X    "5",  "10",  "20",  "25",  "40",  "50",  "80", "100",
  336. X  "125", "140", "150", "170", "200", "250", "270", "300",
  337. X  0
  338. X  } ;
  339. X
  340. Xint NJOB ;
  341. Xchar *Job[] =
  342. X
  343. X  {
  344. X  "engineer",
  345. X  "nurse",
  346. X  "fireman",
  347. X  "mechanic",
  348. X  "programmer",
  349. X  "carpenter",
  350. X  "electrician",
  351. X  "writer",
  352. X  "teacher",
  353. X  "doctor",
  354. X  "attorney",
  355. X  "lawyer",
  356. X  "clerk",
  357. X  "chemist",
  358. X  "librarian",
  359. X  "teller",
  360. X  "physician",
  361. X  "physicist",
  362. X  "chemist",
  363. X  "mathematician",
  364. X  "professor",
  365. X  "driver",
  366. X  "milkman",
  367. X  "gardener",
  368. X  "bricklayer",
  369. X  "guard",
  370. X  "dentist",
  371. X  "curator",
  372. X  "farmer",
  373. X  "stock broker",
  374. X  "letter carrier",
  375. X  "designer",
  376. X  "student",
  377. X  "college student",
  378. X  "high school student",
  379. X  "administrator",
  380. X  "police officer",
  381. X  "investment banker",
  382. X  "politician",
  383. X  0
  384. X  } ;
  385. X
  386. Xint NNAME ;
  387. Xchar *Name[] =
  388. X
  389. X  {
  390. X  "Al",
  391. X  "Alan",
  392. X  "Alice",
  393. X  "Allen",
  394. X  "Alex",
  395. X  "Alexeev",
  396. X  "Amber",
  397. X  "Anne",
  398. X  "Art",
  399. X  "Barbara",
  400. X  "Bart",
  401. X  "Betty",
  402. X  "Bea",
  403. X  "Bill",
  404. X  "Bob",
  405. X  "Bruce",
  406. X  "Bud",
  407. X  "Carl",
  408. X  "Carol",
  409. X  "Cathy",
  410. X  "Cheryl",
  411. X  "Chris",
  412. X  "Christy",
  413. X  "Chuck",
  414. X  "Dale",
  415. X  "Dave",
  416. X  "David",
  417. X  "Dennis",
  418. X  "Diane",
  419. X  "Dick",
  420. X  "Dan",
  421. X  "Don",
  422. X  "Ed",
  423. X  "Elaine",
  424. X  "Ellen",
  425. X  "Francie",
  426. X  "Fred",
  427. X  "Gary",
  428. X  "Helen",
  429. X  "Ingrid",
  430. X  "Frank",
  431. X  "George",
  432. X  "Gilda",
  433. X  "Gus",
  434. X  "Harry",
  435. X  "Henry",
  436. X  "Jack",
  437. X  "James",
  438. X  "Jane",
  439. X  "Janet",
  440. X  "Jeff",
  441. X  "Jessica",
  442. X  "Jill",
  443. X  "Jim",
  444. X  "Joan",
  445. X  "Joe",
  446. X  "John",
  447. X  "Jon",
  448. X  "Kathy",
  449. X  "Kevin",
  450. X  "Karen",
  451. X  "Karl",
  452. X  "Keith",
  453. X  "Ken",
  454. X  "Kent",
  455. X  "Kristen",
  456. X  "Kurt",
  457. X  "Larry",
  458. X  "Lauren",
  459. X  "Liholiho",
  460. X  "Linda",
  461. X  "Lou",
  462. X  "Lynda",
  463. X  "Lynn",
  464. X  "Marc",
  465. X  "Margaret",
  466. X  "Marv",
  467. X  "Maria",
  468. X  "Mark",
  469. X  "Marty",
  470. X  "Mary",
  471. X  "Mike",
  472. X  "Monica",
  473. X  "Nancy",
  474. X  "Neil",
  475. X  "Noelani",
  476. X  "Oliver",
  477. X  "Olivia",
  478. X  "Pat",
  479. X  "Patrick",
  480. X  "Paul",
  481. X  "Paula",
  482. X  "Peter",
  483. X  "Phil",
  484. X  "Ralph",
  485. X  "Ray",
  486. X  "Rex",
  487. X  "Rich",
  488. X  "Rick",
  489. X  "Roy",
  490. X  "Ron",
  491. X  "Sally",
  492. X  "Sam",
  493. X  "Scott",
  494. X  "Scottie",
  495. X  "Spencer",
  496. X  "Steve",
  497. X  "Stu",
  498. X  "Sue",
  499. X  "Terry",
  500. X  "Tim",
  501. X  "Todd",
  502. X  "Tom",
  503. X  "Tony",
  504. X  "Thomas",
  505. X  "Walt",
  506. X  "Wendy",
  507. X  "William",
  508. X  "Zelda",
  509. X  0
  510. X  } ;
  511. X
  512. Xint NCALLSIGN ;
  513. Xchar *Sender, *Receiver ;
  514. Xchar *CallSign[] =
  515. X
  516. X  {
  517. X  "AA0ET",
  518. X  "AA4LR",
  519. X  "AA5BT",
  520. X  "AA6NP",
  521. X  "AA6YD",
  522. X  "AA9BK",
  523. X  "AB5AP",
  524. X  "AB6FI",
  525. X  "AC4HF",
  526. X  "G0GWA",
  527. X  "GM4ZNX",
  528. X  "KA0WCH",
  529. X  "KA1AXY",
  530. X  "KA1CV",
  531. X  "KA1UTU",
  532. X  "KA1ZGC",
  533. X  "KA6S",
  534. X  "KA2RAF",
  535. X  "KB0CY",
  536. X  "KB2NRH",
  537. X  "KB6CSP",
  538. X  "KB6JXT",
  539. X  "KC6SKV",
  540. X  "KC6SSS",
  541. X  "KC6TDR",
  542. X  "KC6VWV",
  543. X  "KD3FU",
  544. X  "KD4AUS",
  545. X  "KD4CPL",
  546. X  "KE2TP",
  547. X  "KE4ZV",
  548. X  "KF8NH",
  549. X  "KF6BZF",
  550. X  "KJ6NN",
  551. X  "KJ9U",
  552. X  "KK6JQ",
  553. X  "KM3T",
  554. X  "KT7H",
  555. X  "K2WK",
  556. X  "K5RC",
  557. X  "K6XO",
  558. X  "K6OCK",
  559. X  "K9ALD",
  560. X  "IK5AAX",
  561. X  "I5FLN",
  562. X  "JA1BLV",
  563. X  "N1AL",
  564. X  "N1JCX",
  565. X  "N4PBK",
  566. X  "N4VRN",
  567. X  "N5IAL",
  568. X  "N5OP",
  569. X  "N6BIS",
  570. X  "N6MWC",
  571. X  "N6TTO",
  572. X  "N8EMR",
  573. X  "N9MYI",
  574. X  "N9FZX",
  575. X  "N9JRV",
  576. X  "N9LFF",
  577. X  "NE3X",
  578. X  "NH6ZW",
  579. X  "NJ7E",
  580. X  "NR3Z",
  581. X  "NT1G",
  582. X  "OD5NG",
  583. X  "OH3BK",
  584. X  "OH8NUP",
  585. X  "TG9VT",
  586. X  "UT5RP",
  587. X  "VE6MGS",
  588. X  "VE7EMD",
  589. X  "VK2BQS",
  590. X  "VK2EG",
  591. X  "W0PBV",
  592. X  "W0RIJ",
  593. X  "W0RSB",
  594. X  "WA1UXA",
  595. X  "WA2AGE",
  596. X  "WA3EEC",
  597. X  "WA3TBL",
  598. X  "WA3UQV",
  599. X  "WA5RPF",
  600. X  "WA6DGX",
  601. X  "WA7VYJ",
  602. X  "WA8ZGO",
  603. X  "WB4JCM",
  604. X  "WB5FDP",
  605. X  "WB5FKH",
  606. X  "WB5NRN",
  607. X  "WB2CJL",
  608. X  "WB7CJO",
  609. X  "WB7EEL",
  610. X  "WB7TZA",
  611. X  "WB8EOH",
  612. X  "WB9IVR",
  613. X  "WD0EIB",
  614. X  "WX9T",
  615. X  "W2FG",
  616. X  "W2JGR",
  617. X  "W3GRG",
  618. X  "W3OTC",
  619. X  0
  620. X  } ;
  621. X
  622. Xint NLICENSE ;
  623. Xchar *License[] =
  624. X
  625. X  {
  626. X  "Novice",
  627. X  "Technician",
  628. X  "Tech",
  629. X  "General",
  630. X  "Advanced",
  631. X  "Extra",
  632. X  0
  633. X  } ;
  634. X
  635. Xint NCITY ;
  636. Xchar *City[] =
  637. X
  638. X  {
  639. X  "Aiea",
  640. X  "Alexander",
  641. X  "Asbury",
  642. X  "Baker",
  643. X  "Beckley",
  644. X  "Bedford",
  645. X  "Brunswick",
  646. X  "Burnsville",
  647. X  "Clarksville",
  648. X  "Cambridge",
  649. X  "Charleston",
  650. X  "Circleville",
  651. X  "Clarksburg",
  652. X  "Clear Lake",
  653. X  "Cleveland",
  654. X  "Crystal",
  655. X  "Duncanville",
  656. X  "Elizabeth",
  657. X  "Ewa",
  658. X  "Fairbanks",
  659. X  "Fairfield",
  660. X  "Flint",
  661. X  "Gahanna",
  662. X  "Grant",
  663. X  "Greensburg",
  664. X  "Harper",
  665. X  "Honolulu",
  666. X  "Hillsdale",
  667. X  "Jamestown",
  668. X  "Jefferson",
  669. X  "Kaaawa",
  670. X  "Kona",
  671. X  "Lawrenceville",
  672. X  "Lakewood",
  673. X  "Lincoln",
  674. X  "Litchfield",
  675. X  "London",
  676. X  "Long Branch",
  677. X  "Lyndhurst",
  678. X  "Lyndale",
  679. X  "Lynnville",
  680. X  "Mansfield",
  681. X  "Maple",
  682. X  "Meadows",
  683. X  "Mentor",
  684. X  "Mercer",
  685. X  "Mesquite",
  686. X  "Midland",
  687. X  "Milldale",
  688. X  "Milltown",
  689. X  "Moorestown",
  690. X  "Mountain View",
  691. X  "Murray",
  692. X  "Newfield",
  693. X  "Newport",
  694. X  "New London",
  695. X  "Olmstead",
  696. X  "Oak",
  697. X  "Oxnard",
  698. X  "Oxford",
  699. X  "Paradise",
  700. X  "Paris",
  701. X  "Perry",
  702. X  "Potter",
  703. X  "Pottsville",
  704. X  "Redwood",
  705. X  "Russellville",
  706. X  "Salem",
  707. X  "Sandy",
  708. X  "Saratoga",
  709. X  "Smithville",
  710. X  "Springdale",
  711. X  "Springfield",
  712. X  "Starkville",
  713. X  "Sunnyvale",
  714. X  "Tinker",
  715. X  "Trenton",
  716. X  "Walnut",
  717. X  "Warren",
  718. X  "Warsaw",
  719. X  "Washington",
  720. X  "Weston",
  721. X  "Wheatfield",
  722. X  "Williamson",
  723. X  "Worchester",
  724. X  "Zolton",
  725. X  0
  726. X  } ;
  727. X
  728. Xint NNEWCITY ;
  729. Xchar *NewCity[] =
  730. X
  731. X  {
  732. X  "Albany",
  733. X  "Avalon",
  734. X  "Barnard",
  735. X  "Brunswick",
  736. X  "Bedford",
  737. X  "Chester",
  738. X  "Conway",
  739. X  "Dime Box",
  740. X  "Franklin",
  741. X  "Granville",
  742. X  "Hamilton",
  743. X  "Morris",
  744. X  "Oxford",
  745. X  "Salisbury",
  746. X  "Stafford",
  747. X  "Stanton",
  748. X  "Trenton",
  749. X  "Troy",
  750. X  "Walpole",
  751. X  "Warren",
  752. X  "Wilton",
  753. X  "Weston",
  754. X  "Windsor",
  755. X  "Zulch",
  756. X  0
  757. X  } ;
  758. X
  759. Xint NCITYHTS ;
  760. Xchar *CityHeights[] =
  761. X
  762. X  {
  763. X  "Apple",
  764. X  "Ashford",
  765. X  "Baker",
  766. X  "Baldwin",
  767. X  "Banner",
  768. X  "Barnard",
  769. X  "Benton",
  770. X  "Carson",
  771. X  "Chester",
  772. X  "Conway",
  773. X  "Cornwall",
  774. X  "Crystal",
  775. X  "Fletcher",
  776. X  "Franklin",
  777. X  "Granite",
  778. X  "Grant",
  779. X  "Harper",
  780. X  "Jefferson",
  781. X  "Hamilton",
  782. X  "Hickory",
  783. X  "Lincoln",
  784. X  "Maple",
  785. X  "Mercer",
  786. X  "Morgan",
  787. X  "Morris",
  788. X  "Murray",
  789. X  "Oak",
  790. X  "Orwell",
  791. X  "Quail",
  792. X  "Perry",
  793. X  "Potter",
  794. X  "Salem",
  795. X  "Stafford",
  796. X  "Stone",
  797. X  "Tinker",
  798. X  "Walnut",
  799. X  "Warren",
  800. X  "Washington",
  801. X  "Weston",
  802. X  "Wilton",
  803. X  0
  804. X  } ;
  805. X
  806. Xint NNEW ;
  807. Xchar *New[] =
  808. X
  809. X  {
  810. X  "New",
  811. X  "Old",
  812. X  "North",
  813. X  "South",
  814. X  "East",
  815. X  "West",
  816. X  0
  817. X  } ;
  818. X
  819. Xint NHEIGHTS ;
  820. Xchar *Heights[] =
  821. X
  822. X  {
  823. X  "Castle",
  824. X  "Heights",
  825. X  "Island",
  826. X  "Valley",
  827. X  "City",
  828. X  "Creek",
  829. X  "Park",
  830. X  "Mill",
  831. X  "Neck",
  832. X  0
  833. X  } ;
  834. X
  835. Xint NSTATE ;
  836. Xchar *State[] =
  837. X
  838. X  {
  839. X  "Alabama",
  840. X  "Alaska",
  841. X  "Arizona",
  842. X  "Arkansas",
  843. X  "California",
  844. X  "Colorado",
  845. X  "Connecticut",
  846. X  "Delaware",
  847. X  "Florida",
  848. X  "Gaum",
  849. X  "Georgia",
  850. X  "Hawaii",
  851. X  "Idaho",
  852. X  "Illinois",
  853. X  "Indiana",
  854. X  "Iowa",
  855. X  "Kansas",
  856. X  "Kentucky",
  857. X  "Louisiana",
  858. X  "Maine",
  859. X  "Maryland",
  860. X  "Massachusetts",
  861. X  "Michigan",
  862. X  "Midway",
  863. X  "Minnesota",
  864. X  "Mississippi",
  865. X  "Missouri",
  866. X  "Montana",
  867. X  "Nebraska",
  868. X  "Nevada",
  869. X  "New Hampshire",
  870. X  "New Jersey",
  871. X  "New Mexico",
  872. X  "New York",
  873. X  "North Carolina",
  874. X  "North Dakota",
  875. X  "Ohio",
  876. X  "Oklahoma",
  877. X  "Oregon",
  878. X  "Pennsylvania",
  879. X  "Puerto Rico",
  880. X  "Rhode Island",
  881. X  "Saipan",
  882. X  "American Samoa",
  883. X  "South Carolina",
  884. X  "South Dakota",
  885. X  "Tennessee",
  886. X  "Texas",
  887. X  "Utah",
  888. X  "Vermont",
  889. X  "Virginia",
  890. X  "Virgin Islands",
  891. X  "Wake Island",
  892. X  "Washington",
  893. X  "West Virginia",
  894. X  "Wisconsin",
  895. X  "Wyoming",
  896. X  0
  897. X  } ;
  898. X
  899. Xint NMISC ;
  900. Xchar *Miscellaneous[] =
  901. X  {
  902. X  "I sometimes work packet on vhf.",
  903. X  "I sometimes work packet on vhf.",
  904. X  "We are on vacation and I am mobile.",
  905. X  "We are on vacation and I am mobile.",
  906. X  "Your signal is chirpy.",
  907. X  "Lots of QRM.",
  908. X  "Lots of QRM.",
  909. X  "Should we QSY?",
  910. X  "Please QRS.",
  911. X  "Please QRS.",
  912. X  "Tnx for the report.",
  913. X  "Thanks for the call.",
  914. X  "Tnx for the call.",
  915. X  "Tnx for ur call.",
  916. X  "QRM",
  917. X  "QRM?",
  918. X  "QRS",
  919. X  "QRS?",
  920. X  "QSY?",
  921. X  "QSK?",
  922. X  "QRX?",
  923. X  "QTH?",
  924. X  "QTR?",
  925. X  "What is your QTH?",
  926. X  "Is it green there or brown?",
  927. X  "Where do you live?",
  928. X  "Where do you live?",
  929. X  "Where do you live now?",
  930. X  "How long have you been a radio amateur?",
  931. X  "How long have you been a radio amateur?",
  932. X  "What are your hobbies?",
  933. X  "What is your hobby?",
  934. X  "Must QRT for dinner.",
  935. X  "Must QRT for dinner.",
  936. X  "Must QRT for hot dinner.",
  937. X  "Must QRT for cold dinner.",
  938. X  "Must QRT for lunch.",
  939. X  "Must QRT for lunch.",
  940. X  "Must QRT for hot lunch.",
  941. X  "Must QRT for sleep.",
  942. X  "Must QRT for some sleep.",
  943. X  "Must QRT for bathroom break.",
  944. X  "Must QRT, lightning threatens.",
  945. X  "Must QRT, lightning storm has started.",
  946. X  "Must QRT, tornado sirens sounding.",
  947. X  "Must QRT, tsunami sirens sounding.",
  948. X  "Must QRT to hear news about approaching hurricane.",
  949. X  "Must QRT, weather radio warbling.",
  950. X  "Must QRT invading tanks making too much noise outside to hear you.",
  951. X  "Must QRT occupation forces knocking at door.",
  952. X  "I am mobile and am going to the office.",
  953. X  "I am mobile and am going to work.",
  954. X  "I am mobile and driving to work.",
  955. X  "I am mobile, driving home from work.",
  956. X  "I am mobile, stuck in traffic.",
  957. X  "I am mobile, driving cross country.",
  958. X  "I am mobile, riding a Peruvian Paso Fino horse.",
  959. X  "Ive fallen and I cant get up.",
  960. X  "How is my signal?",
  961. X  "Hows my signal?",
  962. X  "How copy so far?",
  963. X  "How copy so far?",
  964. X  "How copy?",
  965. X  "Copy?",
  966. X  "Copy?",
  967. X  "Cpy?",
  968. X  "Do you understand English?",
  969. X  "Do u understand English?",
  970. X  "Habla espanol?",
  971. X  "Sprechen Sie Deutsch?",
  972. X  "What is your job?",
  973. X  "Whats your job?",
  974. X  "How is the weather?",
  975. X  "Hows the weather?",
  976. X  "How is the weather?",
  977. X  "Are you using a linear amplifier?",
  978. X  "ru using linear amplifier?",
  979. X  "I am using a linear amplifier.",
  980. X  "am using a linear amplifier.",
  981. X  "Are you using a linear amplifier?",
  982. X  "You are using a nonlinear amplifier?",
  983. X  "Propagation is good.",
  984. X  "Propagation is good.",
  985. X  "Propagation is very good.",
  986. X  "Propagation is poor.",
  987. X  "Propagation is very poor.",
  988. X  "Are you on daylight savings time?",
  989. X  "Did you hear the news?",
  990. X  "Did you hear news?",
  991. X  "Is the bad news true?",
  992. X  "Sorry, stack of books just fell over.",
  993. X  "There is an eclipse of the moon right now.",
  994. X  "Do you recycle often?",
  995. X  "Do you prefer metric units?",
  996. X  "We just felt a small quake here.",
  997. X  "Whoa, we are having an earthquake here. A real roller.",
  998. X  "You are my first contact today.",
  999. X  "You are my second contact today.",
  1000. X  "You are my last contact today.",
  1001. X  "Are you married?",
  1002. X  "Do you have a horse?",
  1003. X  "Do you have a dog?",
  1004. X  "Do you have a cat?",
  1005. X  "Do you have a ferret?",
  1006. X  "Do you have a gecko?",
  1007. X  "A clumsy gecko just fell on my hand.",
  1008. X  "How old is your rig?",
  1009. X  "How did you learn morse code?",
  1010. X  "Do you know morse code?",
  1011. X  "When did you start to learn morse code?",
  1012. X  "Are you good at calculus? I have a question for you.",
  1013. X  "Are you good at group theory? I have a question for you.",
  1014. X  "Can you pick master locks? Those are supposed to be easy.",
  1015. X  "Can you pick kryptonite locks?",
  1016. X  "QLF?",
  1017. X  "There is a rainbow outside the window.",
  1018. X  "I just saw a bolide.",
  1019. X  "Do you know the word copacetic?",
  1020. X  "Do you know the word garralous?",
  1021. X  "What time zone are you in?",
  1022. X  "Would you have given Morse a Nobel prize?",
  1023. X  "Our neighbors have a horse named morse.",
  1024. X  "What is your elevation?",
  1025. X  "What is the air pressure there?",
  1026. X  "I sometimes monitor ulf for earthquake precursors.",
  1027. X  "Can you think of something else interesting to say?",
  1028. X  "+@=x/,? 73 just testing you.",
  1029. X  "@w=+/,? 73 just testing you.",
  1030. X  ",?/=+9@ 73 just testing you.",
  1031. X  ",?/=q+@ 73 just testing u.",
  1032. X  0
  1033. X  };
  1034. X
  1035. Xint NRST ;
  1036. Xchar *RST[] =
  1037. X
  1038. X  {
  1039. X  "555",
  1040. X  "577",
  1041. X  "578",
  1042. X  "579",
  1043. X  "588",
  1044. X  "589",
  1045. X  "599",
  1046. X  "478",
  1047. X  "354",
  1048. X  "248",
  1049. X  "126",
  1050. X  0
  1051. X  } ;
  1052. X
  1053. X/*
  1054. X ********************
  1055. X * Utility routines *
  1056. X ********************
  1057. X */
  1058. X
  1059. Xint CountStrings(StringVector) char *StringVector[] ;
  1060. X
  1061. X  /*
  1062. X   * Count the number of string values in the supplied vector
  1063. X   * of pointers. Start with the first pointer and stop when
  1064. X   * NIL (0) is encountered.
  1065. X   */
  1066. X
  1067. X  {
  1068. X  register char **SV ;
  1069. X  register int Count ;
  1070. X
  1071. X  Count = 0 ;
  1072. X
  1073. X  for (SV = StringVector ; *SV ; SV++)
  1074. X    {
  1075. X    Count++ ;
  1076. X    }
  1077. X  return(Count) ;
  1078. X  }
  1079. X
  1080. Xint Roll(Number) int Number ;
  1081. X
  1082. X  {
  1083. X  double drand48() ;
  1084. X  return( (int)(drand48() * (Number/*-1*/)) ) ;
  1085. X  }
  1086. X
  1087. Xchar *Choose(Words, Number) char *Words[] ; int Number ;
  1088. X
  1089. X  {
  1090. X  return( Words[ Roll(Number) ] ) ;
  1091. X  }
  1092. X
  1093. X/*
  1094. X *************************************
  1095. X * Routines to put sentences/clauses *
  1096. X *************************************
  1097. X */
  1098. X
  1099. Xvoid PutMisc()
  1100. X
  1101. X  {
  1102. X  printf("%s\n", Choose(Miscellaneous, NMISC)) ;
  1103. X  }
  1104. X
  1105. Xvoid PutThanks()
  1106. X
  1107. X  {
  1108. X  switch(Roll(6))
  1109. X    {
  1110. X    case 0:
  1111. X      printf("Thanks for your call.\n") ;
  1112. X      break ;
  1113. X    case 1:
  1114. X      printf("Tnx for ur call.\n") ;
  1115. X      break ;
  1116. X    case 2:
  1117. X      printf("Tnx for the call.\n") ;
  1118. X      break ;
  1119. X    case 3:
  1120. X      printf("Thanks for the call.\n") ;
  1121. X      break ;
  1122. X    default:
  1123. X      printf("Thanks %s for the call.\n", Choose(Name, NNAME)) ;
  1124. X      break ;
  1125. X    }
  1126. X  }
  1127. X
  1128. Xvoid PutName()
  1129. X
  1130. X  {
  1131. X  switch (Roll(4))
  1132. X    {
  1133. X    case 0:
  1134. X      printf("Name is %s.\n", Choose(Name, NNAME)) ;
  1135. X      break ;
  1136. X    case 1:
  1137. X      printf("This is %s.\n", Choose(Name, NNAME)) ;
  1138. X      break ;
  1139. X    case 2:
  1140. X      printf("%s here.\n", Choose(Name, NNAME)) ;
  1141. X      break ;
  1142. X    default:
  1143. X      printf("My name is %s.\n", Choose(Name, NNAME)) ;
  1144. X      break ;
  1145. X    }
  1146. X  }
  1147. X
  1148. Xvoid PutJob()
  1149. X
  1150. X  {
  1151. X  switch(Roll(10))
  1152. X    {
  1153. X    case 0:
  1154. X    case 1:
  1155. X      printf("Occupation is %s.\n", Choose(Job, NJOB)) ;
  1156. X      break ;
  1157. X    case 2:
  1158. X    case 3:
  1159. X      printf("My occupation is %s.\n", Choose(Job, NJOB)) ;
  1160. X      break ;
  1161. X    case 4:
  1162. X    case 5:
  1163. X      printf("I work as a %s.\n",  Choose(Job, NJOB)) ;
  1164. X      break ;
  1165. X    case 6:
  1166. X      printf("I was a %s, now unemployed.\n",  Choose(Job, NJOB)) ;
  1167. X      break ;
  1168. X    default:
  1169. X      printf("I am a %s.\n", Choose(Job, NJOB)) ;
  1170. X      break ;
  1171. X    }
  1172. X  }
  1173. X
  1174. Xvoid PutAge()
  1175. X
  1176. X  {
  1177. X  switch(Roll(3))
  1178. X    {
  1179. X    case 0:
  1180. X      printf("I am %d years old.\n", Roll(60)+16) ;
  1181. X      break ;
  1182. X    case 1:
  1183. X      printf("My age is %d.\n", Roll(60)+16) ;
  1184. X      break ;
  1185. X    default:
  1186. X      printf("Age is %d.\n", Roll(60)+16) ;
  1187. X      break ;
  1188. X    }
  1189. X  }
  1190. X
  1191. Xvoid PutLicense()
  1192. X
  1193. X  {
  1194. X  switch(Roll(4))
  1195. X    {
  1196. X    case 0:
  1197. X      printf("I have a %s class license.\n", Choose(License, NLICENSE)) ;
  1198. X      break ;
  1199. X    case 1:
  1200. X      printf("I am a %s class ham.\n", Choose(License, NLICENSE)) ;
  1201. X      break ;
  1202. X    case 2:
  1203. X      printf("I have been licensed %d years as %s class.\n",
  1204. X        Roll(20)+1, Choose(License, NLICENSE)) ;
  1205. X      break ;
  1206. X    default:
  1207. X      printf("I have been a %s class ham for %d years.\n",
  1208. X        Choose(License, NLICENSE), Roll(20)+1) ;
  1209. X      break ;
  1210. X    }
  1211. X  }
  1212. X
  1213. Xvoid PutTemperature()
  1214. X
  1215. X  {
  1216. X  printf("Temperature is %d.\n", Roll(80) + 10) ;
  1217. X  }
  1218. X
  1219. Xvoid PutWeather1()
  1220. X
  1221. X  {
  1222. X  switch (Roll(14))
  1223. X    {
  1224. X    case 0:
  1225. X      printf("Weather here is %s.\n", Choose(Weather1, NWX1)) ;
  1226. X      PutTemperature() ;
  1227. X      break ;
  1228. X    case 1:
  1229. X      printf("Weather is %s.\n", Choose(Weather1, NWX1)) ;
  1230. X      PutTemperature() ;
  1231. X      break ;
  1232. X    case 2:
  1233. X      printf("WX is %s.\n", Choose(Weather1, NWX1)) ;
  1234. X      PutTemperature() ;
  1235. X      break ;
  1236. X    case 3:
  1237. X      printf("Weather here is %s.\n", Choose(Weather1, NWX1)) ;
  1238. X      break ;
  1239. X    case 4:
  1240. X      printf("Weather is %s.\n", Choose(Weather1, NWX1)) ;
  1241. X      break ;
  1242. X    case 5:
  1243. X      printf("WX is %s.\n", Choose(Weather1, NWX1)) ;
  1244. X      break ;
  1245. X    case 6:
  1246. X      PutTemperature() ;
  1247. X      printf("Weather here is %s.\n", Choose(Weather1, NWX1)) ;
  1248. X      break ;
  1249. X    case 7:
  1250. X      PutTemperature() ;
  1251. X      printf("Weather is %s.\n", Choose(Weather1, NWX1)) ;
  1252. X      break ;
  1253. X    case 8:
  1254. X      PutTemperature() ;
  1255. X      printf("WX is %s.\n", Choose(Weather1, NWX1)) ;
  1256. X      break ;
  1257. X    case 9:
  1258. X      printf("Weather here is %s and temperature is %d.\n",
  1259. X        Choose(Weather1, NWX1), Roll(80)+10) ;
  1260. X      break ;
  1261. X    case 10:
  1262. X      printf("Weather is %s, temperature %d.\n",
  1263. X        Choose(Weather1, NWX1), Roll(80)+10) ;
  1264. X      break ;
  1265. X    case 11:
  1266. X      printf("WX is %d degrees and %s.\n",
  1267. X        Roll(80)+10, Choose(Weather1, NWX1));
  1268. X      break ;
  1269. X    case 12:
  1270. X      printf("The WX is %s and the temp is %d degrees.\n",
  1271. X        Choose(Weather1, NWX1), Roll(80)+10) ;
  1272. X      break ;
  1273. X    default:
  1274. X      printf("WX is %s and %d degrees.\n",
  1275. X        Choose(Weather1, NWX1), Roll(80)+10);
  1276. X    }
  1277. X  }
  1278. X
  1279. Xvoid PutWeather2()
  1280. X
  1281. X  {
  1282. X  switch(Roll(5))
  1283. X    {
  1284. X    case 0:
  1285. X      printf("It is %s.\n", Choose(Weather2, NWX2));
  1286. X      break ;
  1287. X    case 1:
  1288. X      printf("It is %s and %d degrees.\n",
  1289. X        Choose(Weather2, NWX2), Roll(80)+10) ;
  1290. X      break ;
  1291. X    case 2:
  1292. X      printf("The WX is %s and the temp is %d degrees.\n",
  1293. X        Choose(Weather2, NWX2), Roll(80)+10) ;
  1294. X      break ;
  1295. X    case 3:
  1296. X      printf("WX is %s and the temp is %d degrees.\n",
  1297. X        Choose(Weather2, NWX2), Roll(80)+10) ;
  1298. X      break ;
  1299. X    default:
  1300. X      printf("It is %s here.\n", Choose(Weather2, NWX2));
  1301. X      break ;
  1302. X    }
  1303. X  }
  1304. X
  1305. Xvoid PutWeather()
  1306. X
  1307. X  {
  1308. X  switch (Roll(2))
  1309. X    {
  1310. X    case 0:
  1311. X      PutWeather1() ;
  1312. X      break ;
  1313. X    default:
  1314. X      PutWeather2() ;
  1315. X      break ;
  1316. X    }
  1317. X  }
  1318. X
  1319. Xvoid PutCityState()
  1320. X
  1321. X  {
  1322. X  switch(Roll(4))
  1323. X    {
  1324. X    case 0:
  1325. X      printf("%s %s, ", Choose(New, NNEW), Choose(NewCity, NNEWCITY)) ;
  1326. X      break ;
  1327. X    case 1:
  1328. X      printf("%s %s, ",
  1329. X        Choose(CityHeights, NCITYHTS), Choose(Heights,NHEIGHTS)) ;
  1330. X      break ;
  1331. X    default:
  1332. X      printf("%s, ", Choose(City, NCITY)) ;
  1333. X      break ;
  1334. X    }
  1335. X  printf("%s.\n", Choose(State, NSTATE)) ;
  1336. X  }
  1337. X
  1338. Xvoid PutLocation()
  1339. X
  1340. X  {
  1341. X  switch(Roll(3))
  1342. X    {
  1343. X    case 0:
  1344. X      printf("My location is ");
  1345. X      break ;
  1346. X    case 1:
  1347. X      printf("My QTH is ") ;
  1348. X      break ;
  1349. X    default:
  1350. X      printf("QTH is ") ;
  1351. X      break ;
  1352. X    }
  1353. X  PutCityState() ;
  1354. X  }
  1355. X
  1356. Xvoid PutRig()
  1357. X
  1358. X  {
  1359. X  switch(Roll(5))
  1360. X    {
  1361. X    case 0:
  1362. X      printf("My rig runs %s watts into a %s up %s feet.\n",
  1363. X        Choose(Power, NPOWER), Choose(Antenna, NANTENNA),
  1364. X        Choose(UpFeet, NUPFEET)) ;
  1365. X      break ;
  1366. X    case 1:
  1367. X      printf("Rig is a %s watt %s and antenna is a %s.\n",
  1368. X        Choose(Power, NPOWER), Choose(Transceiver, NXCVR),
  1369. X        Choose(Antenna, NANTENNA)) ;
  1370. X      break ;
  1371. X    case 2:
  1372. X      printf("My transceiver is a %s.\n", Choose(Transceiver, NXCVR)) ;
  1373. X      printf("It runs %s watts into a %s.\n",
  1374. X        Choose(Power, NPOWER), Choose(Antenna, NANTENNA)) ;
  1375. X      break ;
  1376. X    case 3:
  1377. X      printf("The rig is a %s running %s watts.\n",
  1378. X        Choose(Transceiver, NXCVR), Choose(Power, NPOWER)) ;
  1379. X      printf("Antenna is a %s up %s feet.\n",
  1380. X        Choose(Antenna, NANTENNA), Choose(UpFeet, NUPFEET)) ;
  1381. X      break ;
  1382. X    default:
  1383. X      printf("Rig is a %s running %s watts into a %s up %s feet.\n",
  1384. X        Choose(Transceiver, NXCVR), Choose(Power, NPOWER),
  1385. X        Choose(Antenna, NANTENNA), Choose(UpFeet, NUPFEET)) ;
  1386. X      break ;
  1387. X    }
  1388. X  }
  1389. X
  1390. Xvoid PutRST()
  1391. X
  1392. X  {
  1393. X  register char *TheRST ;
  1394. X
  1395. X  TheRST = Choose(RST, NRST) ;
  1396. X
  1397. X  switch(Roll(8))
  1398. X    {
  1399. X    case 0:
  1400. X      printf("UR RST %s=%s.\n", TheRST, TheRST) ;
  1401. X      break ;
  1402. X    case 1:
  1403. X      printf("RST is %s=%s.\n", TheRST, TheRST) ;
  1404. X      break ;
  1405. X    case 2:
  1406. X      printf("RST %s=%s.\n", TheRST, TheRST) ;
  1407. X      break ;
  1408. X    case 3:
  1409. X      printf("Your RST %s=%s.\n", TheRST, TheRST) ;
  1410. X      break ;
  1411. X    case 4:
  1412. X      printf("Your RST is %s=%s.\n", TheRST, TheRST) ;
  1413. X      break ;
  1414. X    case 5:
  1415. X      printf("Your signal is RST %s/%s.\n", TheRST, TheRST) ;
  1416. X      break ;
  1417. X    case 6:
  1418. X      printf("UR signal is RST %s,%s.\n", TheRST, TheRST) ;
  1419. X      break ;
  1420. X    default:
  1421. X      printf("Your RST is %s/%s.\n", TheRST, TheRST) ;
  1422. X      break ;
  1423. X    }
  1424. X  }
  1425. X
  1426. Xvoid PutFirstCallsign()
  1427. X
  1428. X  {
  1429. X  Sender = Choose(CallSign, NCALLSIGN) ;
  1430. X  Receiver = Choose(CallSign, NCALLSIGN) ;
  1431. X  printf("%s de %s\n", Receiver, Sender) ;
  1432. X  }
  1433. X
  1434. Xvoid PutLastCallsign()
  1435. X
  1436. X  {
  1437. X  printf("%s de %s\n", Receiver, Sender) ;
  1438. X  }
  1439. X
  1440. Xvoid PutForm0()
  1441. X
  1442. X  {
  1443. X  PutRST() ;
  1444. X  PutName() ;
  1445. X  PutLocation() ;
  1446. X  PutMisc() ;
  1447. X  PutRig() ;
  1448. X  PutWeather() ;
  1449. X  PutJob() ;
  1450. X  PutAge() ;
  1451. X  PutMisc() ;
  1452. X  PutLicense() ;
  1453. X  }
  1454. X
  1455. Xvoid PutForm1()
  1456. X
  1457. X  {
  1458. X  PutLocation() ;
  1459. X  PutRST() ;
  1460. X  PutRig() ;
  1461. X  PutWeather() ;
  1462. X  PutMisc() ;
  1463. X  PutName() ;
  1464. X  PutLicense() ;
  1465. X  PutMisc() ;
  1466. X  PutAge() ;
  1467. X  PutJob() ;
  1468. X  }
  1469. X
  1470. Xvoid PutForm2()
  1471. X
  1472. X  {
  1473. X  PutThanks() ;
  1474. X  PutRST() ;
  1475. X  PutName() ;
  1476. X  PutWeather() ;
  1477. X  PutLocation() ;
  1478. X  PutJob() ;
  1479. X  PutLicense() ;
  1480. X  PutRig() ;
  1481. X  PutAge() ;
  1482. X  }
  1483. X
  1484. Xvoid PutForm3()
  1485. X
  1486. X  {
  1487. X  PutLocation() ;
  1488. X  PutRST() ;
  1489. X  PutRig() ;
  1490. X  PutMisc() ;
  1491. X  PutName() ;
  1492. X  PutMisc() ;
  1493. X  PutAge() ;
  1494. X  PutJob() ;
  1495. X  PutLicense() ;
  1496. X  PutMisc() ;
  1497. X  PutWeather() ;
  1498. X  PutMisc() ;
  1499. X  }
  1500. X
  1501. Xvoid PutForm4()
  1502. X
  1503. X  {
  1504. X  PutThanks() ;
  1505. X  PutRST() ;
  1506. X  PutJob() ;
  1507. X  PutMisc() ;
  1508. X  PutMisc() ;
  1509. X  PutName() ;
  1510. X  PutAge() ;
  1511. X  PutLicense() ;
  1512. X  PutRig() ;
  1513. X  PutLocation() ;
  1514. X  PutWeather() ;
  1515. X  PutMisc() ;
  1516. X  }
  1517. X
  1518. Xvoid PutForm5()
  1519. X
  1520. X  {
  1521. X  PutLocation() ;
  1522. X  PutRST() ;
  1523. X  PutRig() ;
  1524. X  PutName() ;
  1525. X  PutJob() ;
  1526. X  PutAge() ;
  1527. X  PutMisc() ;
  1528. X  PutLicense() ;
  1529. X  PutWeather() ;
  1530. X  PutMisc() ;
  1531. X  }
  1532. X
  1533. XPutQSO()
  1534. X
  1535. X  {
  1536. X/*  printf("VVV VVV\n") ; */
  1537. X  PutFirstCallsign() ;
  1538. X  switch(Roll(6))
  1539. X    {
  1540. X    case 0:  PutForm0() ; break ;
  1541. X    case 1:  PutForm1() ; break ;
  1542. X    case 2:  PutForm2() ; break ;
  1543. X    case 3:  PutForm3() ; break ;
  1544. X    case 4:  PutForm4() ; break ;
  1545. X    default: PutForm5() ; break ;
  1546. X    }
  1547. X  printf("+ @\n") ;
  1548. X  PutLastCallsign() ;
  1549. X  printf("\n") ;
  1550. X  }
  1551. X
  1552. Xmain()
  1553. X
  1554. X  {
  1555. X  int i ;
  1556. X
  1557. X  NXCVR     = CountStrings(Transceiver) ;
  1558. X  NANTENNA  = CountStrings(Antenna) ;
  1559. X  NUPFEET   = CountStrings(UpFeet) ;
  1560. X  NPOWER    = CountStrings(Power) ;
  1561. X  NRST      = CountStrings(RST) ;
  1562. X  NWX1      = CountStrings(Weather1) ;
  1563. X  NWX2      = CountStrings(Weather2) ;
  1564. X  NJOB      = CountStrings(Job) ;
  1565. X  NNAME     = CountStrings(Name) ;
  1566. X  NSTATE    = CountStrings(State) ;
  1567. X  NCITY     = CountStrings(City) ;
  1568. X  NCITYHTS  = CountStrings(CityHeights) ;
  1569. X  NNEW      = CountStrings(New) ;
  1570. X  NHEIGHTS  = CountStrings(Heights) ;
  1571. X  NNEWCITY  = CountStrings(NewCity) ;
  1572. X  NLICENSE  = CountStrings(License) ;
  1573. X  NMISC     = CountStrings(Miscellaneous) ;
  1574. X  NCALLSIGN = CountStrings(CallSign) ;
  1575. X
  1576. X  srand48((long) time(0)) ;
  1577. X
  1578. X  PutQSO() ;
  1579. X  }
  1580. END_OF_FILE
  1581. if test 27050 -ne `wc -c <'QSO.c'`; then
  1582.     echo shar: \"'QSO.c'\" unpacked with wrong size!
  1583. fi
  1584. # end of 'QSO.c'
  1585. fi
  1586. if test -f 'alarm.c' -a "${1}" != "-c" ; then 
  1587.   echo shar: Will not clobber existing file \"'alarm.c'\"
  1588. else
  1589. echo shar: Extracting \"'alarm.c'\" \(1440 characters\)
  1590. sed "s/^X//" >'alarm.c' <<'END_OF_FILE'
  1591. X/* alarm.c -- seligman 6/92 */
  1592. X
  1593. X/*
  1594. X-- Implementation of alarm.h
  1595. X*/
  1596. X
  1597. X#include <signal.h>
  1598. X#include <sys/time.h>
  1599. X
  1600. X
  1601. Xstatic int alarmPending = 0;  /* Nonzero when the alarm is set. */
  1602. X
  1603. Xstatic void ualarm();
  1604. Xstatic void AlarmHandler();
  1605. X
  1606. X
  1607. Xvoid AlarmSet(time)
  1608. X    int time;
  1609. X{
  1610. X    alarmPending = 1;
  1611. X    signal(SIGALRM, AlarmHandler);
  1612. X    ualarm(1000 * time, 0);
  1613. X}
  1614. X
  1615. X
  1616. X/*
  1617. X-- If an alarm signal is lurking (due to a prior call to SetAlarm), then
  1618. X-- pause until it arrives.  This procedure could have simply been written:
  1619. X--   if (alarmPending) pause();
  1620. X-- but that allows a potential race condition.
  1621. X*/
  1622. Xvoid AlarmWait()
  1623. X{
  1624. X    long savemask = sigblock(sigmask(SIGALRM));
  1625. X    if (alarmPending)
  1626. X        sigpause(savemask);
  1627. X    sigsetmask(savemask);
  1628. X}
  1629. X
  1630. X
  1631. Xstatic void ualarm(us)
  1632. X    unsigned us;
  1633. X{
  1634. X    struct itimerval rttimer, old_rttimer;
  1635. X
  1636. X    rttimer.it_value.tv_sec  = us / 1000000;
  1637. X    rttimer.it_value.tv_usec = us % 1000000;
  1638. X    rttimer.it_interval.tv_sec  = 0;
  1639. X    rttimer.it_interval.tv_usec = 0;
  1640. X    if (setitimer(ITIMER_REAL, &rttimer, &old_rttimer)) {
  1641. X    perror("ualarm");
  1642. X    exit(1);
  1643. X    }
  1644. X}
  1645. X
  1646. X
  1647. X#ifdef __hpux
  1648. X
  1649. Xstatic void AlarmHandler(sig, code, scp)
  1650. X    int sig;
  1651. X    int code;
  1652. X    struct sigcontext *scp;
  1653. X{
  1654. X    alarmPending = 0;
  1655. X    /* Prevent alarm signal from interrupting any pending read. */
  1656. X    if (scp->sc_syscall == SYS_READ)
  1657. X    scp->sc_syscall_action = SIG_RESTART;
  1658. X}
  1659. X
  1660. X#else
  1661. X
  1662. Xstatic void AlarmHandler()
  1663. X{
  1664. X    alarmPending = 0;
  1665. X}
  1666. X
  1667. X#endif __hpux
  1668. END_OF_FILE
  1669. if test 1440 -ne `wc -c <'alarm.c'`; then
  1670.     echo shar: \"'alarm.c'\" unpacked with wrong size!
  1671. fi
  1672. # end of 'alarm.c'
  1673. fi
  1674. if test -f 'alarm.h' -a "${1}" != "-c" ; then 
  1675.   echo shar: Will not clobber existing file \"'alarm.h'\"
  1676. else
  1677. echo shar: Extracting \"'alarm.h'\" \(450 characters\)
  1678. sed "s/^X//" >'alarm.h' <<'END_OF_FILE'
  1679. X/* alarm.h -- seligman 6/92 */
  1680. X
  1681. X/*
  1682. X-- Routines for using the system interval timer to time beeps.  Useful
  1683. X-- for implementing the functions in beep.h on systems that don't provide
  1684. X-- a more straightforward BeepWait() equivalent.
  1685. X--
  1686. X-- These routines use the ALRM signal.
  1687. X*/
  1688. X
  1689. X
  1690. X/*
  1691. X-- Set the alarm for a time specified in ms.
  1692. X*/
  1693. Xvoid AlarmSet(/*int time*/);
  1694. X
  1695. X/*
  1696. X-- Wait for the alarm, or return immediately if the alarm isn't set.
  1697. X*/
  1698. Xvoid AlarmWait();
  1699. END_OF_FILE
  1700. if test 450 -ne `wc -c <'alarm.h'`; then
  1701.     echo shar: \"'alarm.h'\" unpacked with wrong size!
  1702. fi
  1703. # end of 'alarm.h'
  1704. fi
  1705. if test -f 'beep.h' -a "${1}" != "-c" ; then 
  1706.   echo shar: Will not clobber existing file \"'beep.h'\"
  1707. else
  1708. echo shar: Extracting \"'beep.h'\" \(1424 characters\)
  1709. sed "s/^X//" >'beep.h' <<'END_OF_FILE'
  1710. X/* beep.h -- seligman 5/92 */
  1711. X
  1712. X/*
  1713. X-- Machine-dependent code for sounding a beep.
  1714. X*/
  1715. X
  1716. X#ifndef _BEEP_H
  1717. X#define _BEEP_H
  1718. X
  1719. X
  1720. X/*
  1721. X-- Called exactly once, before any other function in this interface.
  1722. X-- Returns nonzero on error.
  1723. X*/
  1724. Xint BeepInit();
  1725. X
  1726. X
  1727. X/*
  1728. X-- Sound a beep for a time specified in ms.
  1729. X-- The volume is in the range [0..100], and the pitch is in Hz.
  1730. X--
  1731. X-- May return immediately, after the sounding of the beep is completed,
  1732. X-- or any time in between.  May be called while a previous beep is still
  1733. X-- sounding, in which case the previous beep finishes before the new one
  1734. X-- begins. Overall timing will be much better if this routine can return
  1735. X-- during the sounding of the beep, especially if it's a "zero-volume beep",
  1736. X-- meaning it's really just the timed pause of silence between tones.
  1737. X-- ("morse.c" tries to do all its thinking during the pauses between beeps,
  1738. X-- mostly in the longer ones between words.)
  1739. X--
  1740. X-- May use the ALRM signal for timing.
  1741. X--
  1742. X-- Returns nonzero on error.
  1743. X*/
  1744. Xint Beep(/*int time, int volume, int pitch*/);
  1745. X
  1746. X
  1747. X/*
  1748. X-- Wait until any currently sounding beeps have completed.
  1749. X-- Returns nonzero on error.
  1750. X*/
  1751. Xint BeepWait();
  1752. X
  1753. X
  1754. X/*
  1755. X-- Clean up any altered state before exiting or suspending the program.
  1756. X-- Returns nonzero on error.
  1757. X*/
  1758. Xint BeepCleanup();
  1759. X
  1760. X
  1761. X/*
  1762. X-- Restore the world when program is resumed after having been suspended.
  1763. X-- Returns nonzero on error.
  1764. X*/
  1765. Xint BeepResume();
  1766. X
  1767. X
  1768. X#endif _BEEP_H
  1769. END_OF_FILE
  1770. if test 1424 -ne `wc -c <'beep.h'`; then
  1771.     echo shar: \"'beep.h'\" unpacked with wrong size!
  1772. fi
  1773. # end of 'beep.h'
  1774. fi
  1775. if test -f 'beepHP.c' -a "${1}" != "-c" ; then 
  1776.   echo shar: Will not clobber existing file \"'beepHP.c'\"
  1777. else
  1778. echo shar: Extracting \"'beepHP.c'\" \(4037 characters\)
  1779. sed "s/^X//" >'beepHP.c' <<'END_OF_FILE'
  1780. X/* beepHP.c -- seligman 5/92 */
  1781. X
  1782. X/*
  1783. X-- Implementation of beep.h for HP9000s700 with audio hardware.
  1784. X--
  1785. X-- If the environment variable SPEAKER begins with "E", the external
  1786. X-- audio connection is used.  If it begins with "I", the internal speaker
  1787. X-- is used.  Otherwise both are used.
  1788. X--
  1789. X-- Compile with the math library "-lm".
  1790. X*/
  1791. X
  1792. X#include "beep.h"
  1793. X#include "alarm.h"
  1794. X#include <stdlib.h>
  1795. X#include <stdio.h>
  1796. X#include <string.h>
  1797. X#include <ctype.h>
  1798. X#include <math.h>
  1799. X#include <fcntl.h>
  1800. X#include <malloc.h>
  1801. X
  1802. X
  1803. Xstatic char *AudioDev;
  1804. X
  1805. Xstatic int DoBeep();
  1806. X
  1807. X
  1808. Xint BeepInit()
  1809. X{
  1810. X    char *speaker = getenv("SPEAKER");
  1811. X    int fd;
  1812. X
  1813. X    AudioDev =   speaker && toupper(speaker[0])=='E'  ?  "/dev/audioEL"
  1814. X           : speaker && toupper(speaker[0])=='I'  ?  "/dev/audioIL"
  1815. X           :                     "/dev/audioBL";
  1816. X
  1817. X    /*
  1818. X    -- A quick check to ensure that we can open the device.
  1819. X    */
  1820. X    if ((fd = open(AudioDev, O_WRONLY)) < 0) {
  1821. X    perror("?? Error opening audio device");
  1822. X    return 1;
  1823. X    }
  1824. X    close(fd);
  1825. X    return 0;
  1826. X}
  1827. X
  1828. X
  1829. X/*
  1830. X-- Optimized for the case where volume & pitch don't change (except possibly
  1831. X-- to zero and back) between successive calls.
  1832. X*/
  1833. Xint Beep(time, volume, pitch)
  1834. X    int time, volume, pitch;
  1835. X{
  1836. X    int rc;
  1837. X
  1838. X    AlarmWait();
  1839. X    if (volume != 0  &&  pitch != 0)
  1840. X    if ((rc = DoBeep(time, volume, pitch))  !=  0)
  1841. X        return rc;
  1842. X    AlarmSet(time);
  1843. X    return 0;
  1844. X}
  1845. X
  1846. X
  1847. Xint BeepWait()
  1848. X{
  1849. X    AlarmWait();
  1850. X    return 0;
  1851. X}
  1852. X
  1853. X
  1854. Xint BeepCleanup()
  1855. X{
  1856. X    return 0;
  1857. X}
  1858. X
  1859. X
  1860. Xint BeepResume()
  1861. X{
  1862. X    return 0;
  1863. X}
  1864. X
  1865. X
  1866. X/*----------------------------------------*/
  1867. X
  1868. X#define SamplingRate 8000        /* audio device samples per second */
  1869. X#define NumRamp (SamplingRate / 200)    /* # samples in 5ms ramp up/down */
  1870. X
  1871. Xtypedef short int Sample;
  1872. X#define MaxSample (Sample)0x7FFF
  1873. X
  1874. X
  1875. X/*
  1876. X-- Sound a beep.
  1877. X-- Optimized for the case where volume & pitch don't change between successive
  1878. X-- calls.
  1879. X*/
  1880. Xstatic int DoBeep(time, volume, pitch)
  1881. X    int time, volume, pitch;
  1882. X{
  1883. X    static int audioDevFD = -1;  /* -1 indicates not yet open. */
  1884. X
  1885. X    /* Save sample buffer from call to call, and reuse it when possible. */
  1886. X    static Sample *buf = NULL;
  1887. X    static int bufLen    = 0;
  1888. X    static int bufVolume = 0;
  1889. X    static int bufPitch  = 0;
  1890. X
  1891. X    Sample rampbuf[NumRamp];  /* Sample buffer for ramp-down. */
  1892. X
  1893. X    /* Are volume and pitch same as previous call? */
  1894. X    int sameVP  =  (volume == bufVolume  &&  pitch == bufPitch);
  1895. X
  1896. X    int i, j;
  1897. X    int numSamples = SamplingRate * time / 1000;
  1898. X
  1899. X    /*
  1900. X    -- It seems that the first write to the audio device after it's
  1901. X    -- been opened must be the longest.
  1902. X    */
  1903. X    if (numSamples > bufLen) {
  1904. X    if (audioDevFD >= 0) close(audioDevFD);
  1905. X    audioDevFD = -1;
  1906. X    }
  1907. X    if (audioDevFD < 0) {
  1908. X    if ((audioDevFD = open(AudioDev, O_WRONLY)) < 0) {
  1909. X        perror("?? Error opening audio device");
  1910. X        return 1;
  1911. X    }
  1912. X    }
  1913. X
  1914. X    /*
  1915. X    -- Allocate space for sample buffer.  Set "i" to lowest index in
  1916. X    -- need of updating.
  1917. X    */
  1918. X    i = sameVP ? bufLen : 0;
  1919. X    if (numSamples > bufLen) {
  1920. X    if (sameVP) {
  1921. X        buf = realloc(buf, numSamples * sizeof(Sample));
  1922. X    } else {
  1923. X        if (buf != NULL) free(buf);
  1924. X        bufVolume = volume;
  1925. X        bufPitch  = pitch;
  1926. X        buf = malloc(numSamples * sizeof(Sample));
  1927. X    }
  1928. X    if (buf == NULL) {
  1929. X        fprintf(stderr, "?? Buy more memory.\n");
  1930. X        return 1;
  1931. X    }
  1932. X    bufLen = numSamples;
  1933. X    }
  1934. X
  1935. X    /*
  1936. X    -- Update any newly-allocated tail of sample buffer.  The ramp-up is
  1937. X    -- handled here (since it always occurs at the same place); the ramp-down
  1938. X    -- is handled later.
  1939. X    */
  1940. X    while (i < bufLen) {
  1941. X    double rampScale  =  (i < NumRamp)  ?  (double) i / NumRamp  :  1;
  1942. X    double t = (double) i / SamplingRate;
  1943. X    buf[i++] =
  1944. X        sin(2 * M_PI * pitch * t) * MaxSample * rampScale * volume / 100;
  1945. X    }
  1946. X
  1947. X    /* Sound the beep, except for the ramp-down. */
  1948. X    write(audioDevFD, buf, (numSamples - NumRamp) * sizeof(Sample));
  1949. X
  1950. X    /* Ramp-down */
  1951. X    for (i = 0, j = numSamples-NumRamp;  i < NumRamp;  i++, j++)
  1952. X    rampbuf[i] = buf[j] * ((double) (NumRamp - i) / NumRamp);
  1953. X    write(audioDevFD, rampbuf, sizeof rampbuf);
  1954. X
  1955. X    return 0;
  1956. X}
  1957. END_OF_FILE
  1958. if test 4037 -ne `wc -c <'beepHP.c'`; then
  1959.     echo shar: \"'beepHP.c'\" unpacked with wrong size!
  1960. fi
  1961. # end of 'beepHP.c'
  1962. fi
  1963. if test -f 'beepSun.c' -a "${1}" != "-c" ; then 
  1964.   echo shar: Will not clobber existing file \"'beepSun.c'\"
  1965. else
  1966. echo shar: Extracting \"'beepSun.c'\" \(4157 characters\)
  1967. sed "s/^X//" >'beepSun.c' <<'END_OF_FILE'
  1968. X/*
  1969. X * If the audio library or audio include files are missing, you need
  1970. X * to get /usr/demo/SOUND off the Sun OS tapes or CD.
  1971. X *
  1972. X * This routine will turn your audio device up to full volume, but
  1973. X * will not attempt to reset the current speaker / jack choice.
  1974. X *
  1975. X * The sun speaker has a residual "click" each time it switches from
  1976. X * silence to tone that I am unable to rid it of.
  1977. X */
  1978. X
  1979. X/* beepSun.c -- seligman 6/92 */
  1980. X
  1981. X/*
  1982. X-- Implementation of beep.h for Sun.
  1983. X-- Rick to Joe to Scott to Joe.
  1984. X*/
  1985. X
  1986. X/* Date: Fri, 2 Aug 91 08:26:08 PDT */
  1987. X/* From: rick@st.unocal.com (Richard Ottolini) */
  1988. X
  1989. X/* Revised: Joe Dellinger */
  1990. X/* Sat Nov 28 02:30:32 HST 1992 */
  1991. X
  1992. X#include "beep.h"
  1993. X#include <sun/audioio.h>
  1994. X#include </usr/demo/SOUND/multimedia/libaudio.h>
  1995. X#include </usr/demo/SOUND/multimedia/ulaw2linear.h>
  1996. X#include <stropts.h>
  1997. X#include <math.h>
  1998. X#include <fcntl.h>
  1999. X
  2000. X
  2001. X#define RATE    (8000)    /* 8 K samples = 1 second */
  2002. X#define RAMP    (RATE * 10 / 1000)    /* 10 millisecond ramp */
  2003. X#define MAXTIME    (2 * RATE)    /* 2 seconds max tone time */
  2004. X
  2005. Xstatic int      audio;
  2006. Xstatic audio_info_t audio_stat;
  2007. X
  2008. Xint
  2009. XBeepInit ()
  2010. X{
  2011. X    audio = open ("/dev/audio", O_WRONLY);
  2012. X
  2013. X    if (audio < 0)
  2014. X    /* Uh oh! */
  2015. X    return 1;
  2016. X    else
  2017. X    {
  2018. X    /*
  2019. X     * Turn the speaker (or headphone, whichever the user has it set to)
  2020. X     * up to full volume.
  2021. X     */
  2022. X    ioctl (audio, AUDIO_GETINFO, &audio_stat);
  2023. X    audio_stat.play.gain = AUDIO_MAX_GAIN;
  2024. X    ioctl (audio, AUDIO_SETINFO, &audio_stat);
  2025. X
  2026. X    return 0;
  2027. X    }
  2028. X}
  2029. X
  2030. X
  2031. Xint
  2032. XBeep (time, volume, pitch)
  2033. X    int             time, volume, pitch;
  2034. X{
  2035. Xstatic unsigned char silence[MAXTIME];
  2036. Xstatic unsigned char soundbuf[MAXTIME - RAMP];
  2037. Xstatic unsigned char ramp_down[RAMP];
  2038. Xstatic int      last_pitch = -1, last_n = -1, last_volume = -1;
  2039. Xstatic int      first_time = 1;
  2040. X
  2041. Xint             i, n, first_len, down_len, cycle;
  2042. Xdouble          dt;
  2043. X
  2044. X/*
  2045. X * Initialize the sound of silence
  2046. X */
  2047. X    if (first_time == 1)
  2048. X    {
  2049. X    for (i = 0; i < MAXTIME; i++)
  2050. X        silence[i] = (unsigned char) 0;
  2051. X    first_time = 0;
  2052. X    }
  2053. X
  2054. X
  2055. X/*
  2056. X * Finagle the number of samples
  2057. X */
  2058. X    n = (time / 1000.) * RATE;    /* Number samples in tone time */
  2059. X    n = n < MAXTIME ? n : MAXTIME;    /* clip to buffer size */
  2060. X    n = n < 2 * RAMP ? 2 * RAMP : n;    /* leave room for ramps */
  2061. X
  2062. X/*
  2063. X * Catch stupidity
  2064. X */
  2065. X    if (pitch <= 0)
  2066. X    volume = 0;
  2067. X
  2068. X
  2069. X    if (volume <= 0)
  2070. X    {
  2071. X    write (audio, silence, n);
  2072. X    }
  2073. X    else
  2074. X    {
  2075. X/*
  2076. X * clip to Nyquist
  2077. X * (Of course this means that if you ask for too high a frequency you
  2078. X * just get silence, since you sample all the zero-crossings of the
  2079. X * sine wave.)
  2080. X */
  2081. X    pitch = pitch < RATE / 2 ? pitch : RATE / 2;
  2082. X    cycle = ((RATE + 1.e-6) / pitch);    /* samples per cycle */
  2083. X
  2084. X    if (cycle > MAXTIME / 2)
  2085. X        cycle = MAXTIME / 2;
  2086. X
  2087. X    /* round down length of (rampup + mesa top) to integral cycle */
  2088. X    first_len = ((n - RAMP) / cycle) * cycle;
  2089. X    if (first_len < cycle)
  2090. X        first_len = cycle;
  2091. X    if (first_len > MAXTIME - RAMP)
  2092. X        first_len = MAXTIME - RAMP;
  2093. X
  2094. X    /* round down length of (rampdown) to integral cycle */
  2095. X    down_len = ((RAMP) / cycle) * cycle;
  2096. X    if (down_len < cycle)
  2097. X        down_len = cycle;
  2098. X    if (down_len > RAMP)
  2099. X        down_len = RAMP;
  2100. X
  2101. X/*
  2102. X * Can we just reuse what we had before?
  2103. X */
  2104. X    if (pitch != last_pitch || n > last_n || volume != last_volume)
  2105. X    {
  2106. X        last_pitch = pitch;
  2107. X        last_n = n;
  2108. X        last_volume = volume;
  2109. X
  2110. X        dt = 2. * M_PI / cycle;    /* sine scale factor */
  2111. X
  2112. X/* Ramp up; begin with silence */
  2113. X
  2114. X        for (i = 0; i < RAMP; i++)
  2115. X        {
  2116. X        soundbuf[i] = audio_l2u (audio_d2l (
  2117. X             ((float) i / RAMP) * (volume / 100.) * sin (i * dt)
  2118. X                            ));
  2119. X        }
  2120. X
  2121. X/* Mesa top */
  2122. X        for (i = RAMP; i < first_len; i++)
  2123. X        {
  2124. X        soundbuf[i] = audio_l2u (audio_d2l (
  2125. X                     1. * (volume / 100.) * sin (i * dt)
  2126. X                            ));
  2127. X        }
  2128. X
  2129. X/* Ramp down; end with silence */
  2130. X        for (i = 0; i < down_len; i++)
  2131. X        {
  2132. X        ramp_down[i] = audio_l2u (audio_d2l (
  2133. X                             (1. - (float) (i + 1) / down_len) * (volume / 100.) * sin (i * dt)
  2134. X                             ));
  2135. X        }
  2136. X    }
  2137. X
  2138. X    write (audio, soundbuf, first_len);
  2139. X    write (audio, ramp_down, down_len);
  2140. X    }
  2141. X
  2142. X    return 0;
  2143. X}
  2144. X
  2145. X
  2146. Xint
  2147. XBeepWait ()
  2148. X{
  2149. X    ioctl (audio, AUDIO_DRAIN);
  2150. X    return 0;
  2151. X}
  2152. X
  2153. X
  2154. Xint
  2155. XBeepCleanup ()
  2156. X{
  2157. X    return 0;
  2158. X}
  2159. X
  2160. X
  2161. Xint
  2162. XBeepResume ()
  2163. X{
  2164. X    return 0;
  2165. X}
  2166. END_OF_FILE
  2167. if test 4157 -ne `wc -c <'beepSun.c'`; then
  2168.     echo shar: \"'beepSun.c'\" unpacked with wrong size!
  2169. fi
  2170. # end of 'beepSun.c'
  2171. fi
  2172. if test -f 'beepX11.c' -a "${1}" != "-c" ; then 
  2173.   echo shar: Will not clobber existing file \"'beepX11.c'\"
  2174. else
  2175. echo shar: Extracting \"'beepX11.c'\" \(1293 characters\)
  2176. sed "s/^X//" >'beepX11.c' <<'END_OF_FILE'
  2177. X/* beepX11.c -- seligman 5/92 */
  2178. X
  2179. X/*
  2180. X-- Implementation of beep.h for X11.
  2181. X--
  2182. X-- Compile with the library "-lX11".
  2183. X*/
  2184. X
  2185. X#include "beep.h"
  2186. X#include <X11/Xlib.h>
  2187. X
  2188. X
  2189. Xstatic Display *dpy = 0;
  2190. Xstatic XKeyboardControl initialState;
  2191. X
  2192. X#define BellFlags (KBBellPercent | KBBellPitch | KBBellDuration)
  2193. X
  2194. X
  2195. Xint BeepInit()
  2196. X{
  2197. X    XKeyboardState state;
  2198. X
  2199. X    if (! (dpy = XOpenDisplay(0))) {
  2200. X    perror("Couldn't open display");
  2201. X    return 1;
  2202. X    }
  2203. X
  2204. X    /* Save initial state so it can be restored later. */
  2205. X    XGetKeyboardControl(dpy, &state);
  2206. X    initialState.bell_duration = state.bell_duration;
  2207. X    initialState.bell_percent  = state.bell_percent;
  2208. X    initialState.bell_pitch    = state.bell_pitch;
  2209. X
  2210. X    return 0;
  2211. X}
  2212. X
  2213. X
  2214. Xint Beep(time, volume, pitch)
  2215. X    int time, volume, pitch;
  2216. X{
  2217. X    XKeyboardControl values;
  2218. X
  2219. X    AlarmWait();
  2220. X
  2221. X    if (volume != 0  &&  pitch != 0) {
  2222. X    values.bell_duration = time;
  2223. X    values.bell_percent  = 100;
  2224. X    values.bell_pitch    = pitch;
  2225. X
  2226. X    XChangeKeyboardControl(dpy, BellFlags, &values);
  2227. X    XBell(dpy, volume - 100);
  2228. X    XFlush(dpy);
  2229. X    }
  2230. X
  2231. X    AlarmSet(time);
  2232. X    return 0;
  2233. X}
  2234. X
  2235. X
  2236. Xint BeepWait()
  2237. X{
  2238. X    AlarmWait();
  2239. X    return 0;
  2240. X}
  2241. X
  2242. X
  2243. Xint BeepCleanup()
  2244. X{
  2245. X    if (dpy != 0) {
  2246. X    XChangeKeyboardControl(dpy, BellFlags, &initialState);
  2247. X    XFlush(dpy);
  2248. X    }
  2249. X    return 0;
  2250. X}
  2251. X
  2252. X
  2253. Xint BeepResume()
  2254. X{
  2255. X    return 0;
  2256. X}
  2257. END_OF_FILE
  2258. if test 1293 -ne `wc -c <'beepX11.c'`; then
  2259.     echo shar: \"'beepX11.c'\" unpacked with wrong size!
  2260. fi
  2261. # end of 'beepX11.c'
  2262. fi
  2263. if test -f 'morse.c' -a "${1}" != "-c" ; then 
  2264.   echo shar: Will not clobber existing file \"'morse.c'\"
  2265. else
  2266. echo shar: Extracting \"'morse.c'\" \(43613 characters\)
  2267. sed "s/^X//" >'morse.c' <<'END_OF_FILE'
  2268. X/*
  2269. X * A morse code practice utility. (Contains those characters that can appear
  2270. X * on the FCC ham license exam.)
  2271. X *
  2272. X * Running "morse" without arguments or input gives self-doc.
  2273. X *
  2274. X * It doesn't keep PERFECT time, but it seems reasonably close
  2275. X * for reasonable word speeds on my slow SUN IPC!
  2276. X *
  2277. X * Joe Dellinger
  2278. X * Tue Aug 11 14:01:02 HST 1992
  2279. X * University of Hawaii at Manoa
  2280. X * 
  2281. X * Revised by Joe:
  2282. X * Thu Nov 26 03:24:19 HST 1992
  2283. X *
  2284. X * Legal stuff:
  2285. X * This code is (ridiculously) heavily modified from morse.c from the Reno UNIX
  2286. X * distribution. I (Joe) also used slightly modified versions of a subroutine
  2287. X * from Richard Ottolini at Unocal for Sun workstation tone generation.
  2288. X * Scott Seligman at Stanford added support for other sorts of devices and
  2289. X * made several other changes. John Shalamskas helped test and made comments.
  2290. X *
  2291. X * I don't think anybody cares if you redistribute this, modify it, etc...
  2292. X * But don't claim you wrote it, try to sell it, or take anyone's name out
  2293. X * of the code! If you modify it, PLEASE INDICATE WHEN, WHERE, AND HOW
  2294. X * YOU MODIFIED IT IN THE COMMENT BELOW. Please.
  2295. X */
  2296. X/*
  2297. X * Joe Dellinger, UH Manoa, inserted this sample modification entry June 1992.
  2298. X */
  2299. X
  2300. X/*
  2301. X * The following stuff is here because this started life as a routine from
  2302. X * the Reno UNIX distribution. (It's also a good boilerplate bit of legalese
  2303. X * to have in there anyway.)
  2304. X */
  2305. X/*
  2306. X * Copyright (c) 1988 Regents of the University of California.
  2307. X * All rights reserved.
  2308. X *
  2309. X * Redistribution and use in source and binary forms, with or without
  2310. X * modification, are permitted provided that the following conditions
  2311. X * are met:
  2312. X * 1. Redistributions of source code must retain the above copyright
  2313. X *    notice, this list of conditions and the following disclaimer.
  2314. X * 2. Redistributions in binary form must reproduce the above copyright
  2315. X *    notice, this list of conditions and the following disclaimer in the
  2316. X *    documentation and/or other materials provided with the distribution.
  2317. X * 3. All advertising materials mentioning features or use of this software
  2318. X *    must display the following acknowledgement:
  2319. X *    This product includes software developed by the University of
  2320. X *    California, Berkeley and its contributors.
  2321. X * 4. Neither the name of the University nor the names of its contributors
  2322. X *    may be used to endorse or promote products derived from this software
  2323. X *    without specific prior written permission.
  2324. X *
  2325. X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  2326. X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  2327. X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  2328. X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  2329. X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  2330. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  2331. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  2332. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  2333. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  2334. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  2335. X * SUCH DAMAGE.
  2336. X */
  2337. X
  2338. X#ifndef lint
  2339. Xchar            copyright[] =
  2340. X"@(#) Copyright (c) 1988 Regents of the University of California.\n\
  2341. X All rights reserved.\n";
  2342. Xchar            copyleftjoe[] =
  2343. X"@(#) Copyright (c) 1992 Joe Dellinger, University of Hawaii at Manoa.\n";
  2344. X#endif            /* not lint */
  2345. X
  2346. X/*
  2347. X *============================================================================
  2348. X * Here starts the code!
  2349. X *============================================================================
  2350. X */
  2351. X/*
  2352. X * Useful for seeing what the interleaved reading and writing loops are
  2353. X * really up to.
  2354. X *
  2355. X * #define DEBUG
  2356. X *
  2357. X * If you want to be overwhelmed with information about the probabilities
  2358. X * of each letter being chosen.
  2359. X *
  2360. X * #define DEBUGG
  2361. X */
  2362. X
  2363. X#include <stdio.h>
  2364. X#include <string.h>
  2365. X#include <sys/types.h>
  2366. X#include <sys/time.h>
  2367. X#include <ctype.h>
  2368. X#include <signal.h>
  2369. X#include "beep.h"
  2370. X/* Define USG for termio a la System V. */
  2371. X#ifdef __hpux
  2372. X#define USG
  2373. X#endif
  2374. X
  2375. X#define FREQUENCY    800.
  2376. X#define FREQUENCY2    602.
  2377. X#define VOLUME        .5
  2378. X#define WORDS_PER_MINUTE    20.
  2379. X#define MAX_BEHINDNESS    0
  2380. X
  2381. Xstatic int      whichfrequ = 0;
  2382. Xstatic float    frequency1 = FREQUENCY;
  2383. Xstatic float    frequency2 = FREQUENCY2;
  2384. Xstatic float    frequency;
  2385. Xstatic float    volume = VOLUME;
  2386. Xstatic float    dot_time;
  2387. Xstatic float    dash_time;
  2388. Xstatic float    intra_char_time;
  2389. Xstatic float    inter_char_time;
  2390. Xstatic float    inter_word_time;
  2391. Xstatic float    catchup_time;
  2392. Xstatic int      showletters = 0;
  2393. Xstatic int      showmorse = 0;
  2394. Xstatic int      wordsbefore = 0;
  2395. Xstatic int      wordsafter = 0;
  2396. Xstatic int      fancyending = 1;
  2397. Xstatic int      noticebad = 0;
  2398. Xstatic int      testing = 0;
  2399. Xstatic int      showtesting = 0;
  2400. Xstatic int      dynamicspeed = 0;
  2401. Xstatic int      charbychar = 0;
  2402. Xstatic int      tryagaincount = 1;
  2403. Xstatic float    words_per_minute;
  2404. Xstatic float    fwords_per_minute;
  2405. Xstatic int      randomletters = 0;
  2406. X#define LETMESEE 2
  2407. Xstatic int      typeaway = 0;
  2408. X
  2409. Xstatic int      totalhitcount = 0;
  2410. Xstatic int      totalmisscount = 0;
  2411. Xstatic int      helpmeflag = 0;
  2412. X
  2413. X#define MAXWORDLEN    20
  2414. X#define TESTBUFSZ (MAXWORDLEN*10)
  2415. Xstatic int      testpointer = -1;
  2416. Xstatic int      testlength = 0;
  2417. Xstatic int      behindness = 0;
  2418. Xstatic int      max_behindness = MAX_BEHINDNESS;
  2419. Xstatic char     teststring[TESTBUFSZ];
  2420. Xstatic int      yourpointer = -1;
  2421. Xstatic int      yourlength = 0;
  2422. Xstatic char     yourstring[TESTBUFSZ];
  2423. X
  2424. X/*
  2425. X * How many times can a given character not be asked before
  2426. X * kicking up the probability of asking that one by one randomfactor unit.
  2427. X */
  2428. X#define RIPECOUNT    64
  2429. X
  2430. X#define TWOFIFTYSIX 256
  2431. Xstatic char    *(code[TWOFIFTYSIX]);
  2432. Xstatic int      errorlog[TWOFIFTYSIX];
  2433. Xstatic int      randomfactor[TWOFIFTYSIX];
  2434. Xstatic int      randomripe[TWOFIFTYSIX];
  2435. Xextern int      testterminal ();
  2436. Xextern int      randomletter ();
  2437. X
  2438. X/*
  2439. X * Value of (Wrong - Right), which, if exceeded, will cause the program
  2440. X * to start prompting you. Above MAX_ERROR_THRESHOLD it will never prompt.
  2441. X * Don't let the user bank too much credit for past correct answers;
  2442. X * limit it by min(ERROR_FLOOR, error_threshold).
  2443. X */
  2444. X#define MAX_ERROR_THRESHOLD        1000
  2445. X#define ERROR_FLOOR            -3
  2446. Xstatic int      error_threshold = MAX_ERROR_THRESHOLD;
  2447. Xstatic int      error_floor = ERROR_FLOOR;
  2448. X
  2449. X/*
  2450. X * How many characters behind before it decides you're having
  2451. X * trouble keeping up.
  2452. X */
  2453. X#define BEHIND        1
  2454. X#define WAYBEHIND    3
  2455. X#define TOOFARBEHIND    6
  2456. X/*
  2457. X * If SLOWPOKE or more wpm ticks go by, then it decides you are having lots
  2458. X * of trouble remembering this character, and need to be asked it more
  2459. X * often.
  2460. X */
  2461. X#define SLOWPOKE    10
  2462. X/* You aren't slow -- you left and came back! */
  2463. X#define SLOWPOKEMAX    (50 * SLOWPOKE)
  2464. X/*
  2465. X * If FASTPOKE or less wpm ticks go by, then it decides you are good at this
  2466. X * character, and need to be asked it less often.
  2467. X */
  2468. X#define FASTPOKE    4
  2469. X
  2470. X/*
  2471. X * These control how quickly the dynamicspeed option acts when you are
  2472. X * fast or slow. Easier to slow down than speed up!
  2473. X */
  2474. X#define ERRORSLOWER    1.04
  2475. X#define ALOTSLOWER    1.15
  2476. X#define ALITTLESLOWER    1.02
  2477. X#define ALITTLEFASTER    1.02
  2478. X
  2479. X/*
  2480. X * How many inter_char_time's to give you to answer after the end of
  2481. X * a word before considering that you are not keeping up.
  2482. X * Maximum of 2.3, minimum of 0.
  2483. X * The bigger the value, the easier it is to kick in the "automatic
  2484. X * speedup" when using the "-d" option. The maximum means you have (almost)
  2485. X * right up to the beginning of the next word to answer and still have it
  2486. X * count as keeping up.
  2487. X */
  2488. X#define SPORTING_RATIO 1.5
  2489. X
  2490. X/*
  2491. X * The bigger, the more evenly things start out.
  2492. X * (Must be at least 2)
  2493. X */
  2494. X#define RANDOMBASELEVEL    7
  2495. X/*
  2496. X * RANDOMINCWORSE scales how badly you are punished for being wrong
  2497. X * or taking too long. RANDOMINCBETTER scales how you are rewarded for
  2498. X * answering quickly or being right.
  2499. X */
  2500. X#define RANDOMINCWORSE    6
  2501. X#define RANDOMINCBETTER    7
  2502. X#define RANDOMMAX    (30 * RANDOMBASELEVEL)
  2503. X/*
  2504. X * The average length of a random word (chosen using exponential distribution).
  2505. X * After implementing this I'm not so sure an exponential distribution
  2506. X * actually models the distribution of real word lengths in English very well.
  2507. X * It's not too bad, though, and the words themselves are all garbage anyway,
  2508. X * so what the heck.
  2509. X */
  2510. X#define RANDWORDLEN    3.5
  2511. X/* Put in a newline instead of a space when past this column */
  2512. X#define RANLINELENGTH    50
  2513. X
  2514. X/* An EOF without the EOF (@) sound */
  2515. X#define SILENTEOF -2
  2516. X/* Toggle tone frequency on control-G within input file */
  2517. X#define FREQU_TOGGLE ((int)'\007')
  2518. X
  2519. X/*
  2520. X * If you want the morse code to come out synchronized with the printing
  2521. X * of dots and dashes with the -m option, then define this. The problem
  2522. X * is that then the morse code then sounds ratty on slower CPU's.
  2523. X * John Shalamskas (KJ9U) suggested turning the precise morse-code printing
  2524. X * synching off because he didn't like the resulting code quality!
  2525. X */
  2526. X#undef FLUSHCODE
  2527. X
  2528. X/*
  2529. X * Choose your favorite random number generator!
  2530. X */
  2531. X#ifndef USERANDOM
  2532. X#ifndef USELRAND
  2533. X#ifndef USERAND
  2534. X#define USERANDOM    /* USELRAND or USERAND are the other choices */
  2535. X#endif
  2536. X#endif
  2537. X#endif
  2538. X
  2539. X#ifdef USERANDOM
  2540. X#define RANDOM()      random()
  2541. X#define SEEDRANDOM(s) srandom((int)s)
  2542. Xlong            random ();
  2543. X#endif
  2544. X#ifdef USELRAND
  2545. X#define RANDOM()      lrand48()
  2546. X#define SEEDRANDOM(s) srand48((long)(s))
  2547. Xlong            lrand48 ();
  2548. X#endif
  2549. X#ifdef USERAND
  2550. X/*
  2551. X * UGH, are you really sure you want to use this one?
  2552. X * This one really stinks!
  2553. X */
  2554. X#define RANDOM()      rand()
  2555. X#define SEEDRANDOM(s) srand((int)(s))
  2556. Xint             rand ();
  2557. X#endif
  2558. X
  2559. Xextern          die (), cleanup (), suspend ();
  2560. X
  2561. Xmain (argc, argv)
  2562. X    int             argc;
  2563. X    char          **argv;
  2564. X{
  2565. Xextern char    *optarg;
  2566. Xextern int      optind;
  2567. Xint             ch;
  2568. Xchar           *p;
  2569. Xint             ii, jj;
  2570. Xint             firsttime, notdoneyet;
  2571. Xint             yourchar;
  2572. Xfloat           randexp, randnum;
  2573. Xextern time_t   time ();
  2574. Xint             linepos;
  2575. X
  2576. X    if (argc == 1 && isatty (fileno (stdin)))
  2577. X    {
  2578. X/*
  2579. X * SELF DOC
  2580. X */
  2581. X    printf ("Usage:\n");
  2582. X    printf ("morse [options] < text_file\n");
  2583. X    printf ("morse [options] words words words\n");
  2584. X    printf ("morse [options] -r\n");
  2585. X    printf ("morse [options] -i\n");
  2586. X    printf ("Options:\n");
  2587. X    printf ("-i    Play what you type.\n");
  2588. X    printf ("-I    Like -i but don't turn off keyboard echoing.\n");
  2589. X    printf ("-r    Generate random text. Starts out slanted towards easy\n");
  2590. X    printf ("      letters, then slants towards ones you get wrong.\n");
  2591. X    printf ("-w words_per_minute (default %g)\n-f frequency_in_hertz (default %g)\n-v volume (zero to one, rather nonlinear, default %g)\n",
  2592. X        WORDS_PER_MINUTE, FREQUENCY, VOLUME);
  2593. X    printf ("-g alternate_frequency (default %g)\n      (toggles via control-G in input FILE at a word break)\n", FREQUENCY2);
  2594. X    printf ("-F Farnsworth_character_words_per_minute\n");
  2595. X    printf ("-e    leave off the EOT sound at the end\n");
  2596. X    printf ("-c    complain about illegal characters instead of just ignoring them\n");
  2597. X    printf ("-b    print each word before doing it\n");
  2598. X    printf ("-a    print each word after doing it\n");
  2599. X    printf ("-l    print each letter just before doing it\n");
  2600. X    printf ("-m    print morse dots and dashes as they sound\n");
  2601. X#ifdef FLUSHCODE
  2602. X    printf ("      (this printing-intensive option slows the wpm down!)\n");
  2603. X#endif
  2604. X    printf ("-t    Type along with the morse, but don't see what\n");
  2605. X    printf ("      you're typing (unless you make a mistake).\n");
  2606. X    printf ("      You are allowed to get ahead as much as you want.\n");
  2607. X    printf ("      If you get too far behind it will stop and resync with you.\n");
  2608. X    printf ("      You can force it to resync at the next word end by hitting control-H.\n");
  2609. X    printf ("      Hit ESC to see how you are doing, control-D to end.\n");
  2610. X    printf ("-T    Like -t but see your characters (after they are played).\n");
  2611. X    printf ("-s    Stop after each character and make sure you get it right. (implies -t)\n");
  2612. X    printf ("-p NUM (default 0)\n");
  2613. X    printf ("      Make you get it right NUM times, for penance. (implies -s)\n");
  2614. X    printf ("      (Yes, NUM = 0 means you can sin all you want.)\n");
  2615. X    printf ("-E NUM  (default %d)\n", MAX_ERROR_THRESHOLD);
  2616. X    printf ("      If your count of wrong answers minus right answers for a given character\n");
  2617. X    printf ("      exceeds this, the program will start prompting you.\n");
  2618. X    printf ("      If %d or above, it will never prompt. (imples -t)\n", MAX_ERROR_THRESHOLD);
  2619. X    printf ("-M NUM (default %d)\n", MAX_BEHINDNESS);
  2620. X    printf ("      If you get more than this number of characters behind, pause until you\n");
  2621. X    printf ("      do your next letter. (1 behind is normal, 0 behind means never pause.)\n");
  2622. X    printf ("      (implies -t)\n");
  2623. X    printf ("-d    Dynamically speed up or slow down depending on how you are doing.\n");
  2624. X    printf ("      (if also -s, then -d _only speeds up_!)\n");
  2625. X    printf ("\n");
  2626. X    printf ("\n");
  2627. X    printf ("\n");
  2628. X    printf ("For the raw beginner trying to learn morse code I recommend\n");
  2629. X    printf ("the following sequence:\n");
  2630. X    printf ("\n");
  2631. X    printf ("Start learning the alphabet:\n");
  2632. X    printf ("    morse -r -s -T -d -w 5 -F 15 -p 5 -E -10\n");
  2633. X    printf ("Then drill drill drill:\n");
  2634. X    printf ("    morse -r -s -T -d -w 5 -F 15 -p 5 -E 0\n");
  2635. X    printf ("Real-time drill, with hints if you really need it:\n");
  2636. X    printf ("    morse -r -T -d -w 5 -F 15 -M 2 -E 4\n");
  2637. X    printf ("Simulated test:\n");
  2638. X    printf ("    QSO | morse -e -T -d -w 5 -F 15\n");
  2639. X    printf ("and the dreaded random-letter test:\n");
  2640. X    printf ("    morse -r -T -d -w 5 -F 15\n");
  2641. X    printf ("\n");
  2642. X    printf ("Written by (mostly) joe@montebello.soest.hawaii.edu\n");
  2643. X    exit (0);
  2644. X    }
  2645. X
  2646. X    for (ii = 0; ii < TWOFIFTYSIX; ii++)
  2647. X    code[ii] = NULL;
  2648. X
  2649. X/* Load in the morse code code */
  2650. X    code[(int) '0'] = "-----";
  2651. X    code[(int) '1'] = ".----";
  2652. X    code[(int) '2'] = "..---";
  2653. X    code[(int) '3'] = "...--";
  2654. X    code[(int) '4'] = "....-";
  2655. X    code[(int) '5'] = ".....";
  2656. X    code[(int) '6'] = "-....";
  2657. X    code[(int) '7'] = "--...";
  2658. X    code[(int) '8'] = "---..";
  2659. X    code[(int) '9'] = "----.";
  2660. X
  2661. X    code[(int) 'a'] = ".-";
  2662. X    code[(int) 'b'] = "-...";
  2663. X    code[(int) 'c'] = "-.-.";
  2664. X    code[(int) 'd'] = "-..";
  2665. X    code[(int) 'e'] = ".";
  2666. X    code[(int) 'f'] = "..-.";
  2667. X    code[(int) 'g'] = "--.";
  2668. X    code[(int) 'h'] = "....";
  2669. X    code[(int) 'i'] = "..";
  2670. X    code[(int) 'j'] = ".---";
  2671. X    code[(int) 'k'] = "-.-";
  2672. X    code[(int) 'l'] = ".-..";
  2673. X    code[(int) 'm'] = "--";
  2674. X    code[(int) 'n'] = "-.";
  2675. X    code[(int) 'o'] = "---";
  2676. X    code[(int) 'p'] = ".--.";
  2677. X    code[(int) 'q'] = "--.-";
  2678. X    code[(int) 'r'] = ".-.";
  2679. X    code[(int) 's'] = "...";
  2680. X    code[(int) 't'] = "-";
  2681. X    code[(int) 'u'] = "..-";
  2682. X    code[(int) 'v'] = "...-";
  2683. X    code[(int) 'w'] = ".--";
  2684. X    code[(int) 'x'] = "-..-";
  2685. X    code[(int) 'y'] = "-.--";
  2686. X    code[(int) 'z'] = "--..";
  2687. X
  2688. X    /* Punctuation */
  2689. X    code[(int) '='] = "-...-";
  2690. X    code[(int) '?'] = "..--..";
  2691. X    code[(int) '/'] = "-..-.";
  2692. X    code[(int) ','] = "--..--";
  2693. X    code[(int) '.'] = ".-.-.-";
  2694. X
  2695. X    /* Procedural signs */
  2696. X    code[(int) '+'] = ".-.-.";
  2697. X    code[(int) '@'] = "...-.-";
  2698. X
  2699. X    for (ii = 0; ii < TWOFIFTYSIX; ii++)
  2700. X    {
  2701. X    /* Everything starts equally fresh */
  2702. X    randomripe[ii] = 0;
  2703. X    /* Start out assuming you know how everything sounds */
  2704. X    errorlog[ii] = 0;
  2705. X
  2706. X    if (code[ii] == NULL)
  2707. X    {
  2708. X        /* Ensures these will never be chosen */
  2709. X        randomfactor[ii] = 0;
  2710. X    }
  2711. X    else
  2712. X    {
  2713. X        /* Start out favoring easy ones */
  2714. X        randomfactor[ii] = RANDOMBASELEVEL - strlen (code[ii]);
  2715. X        if (randomfactor[ii] < 1)
  2716. X        randomfactor[ii] == 1;
  2717. X    }
  2718. X    }
  2719. X
  2720. X    words_per_minute = WORDS_PER_MINUTE;
  2721. X    fwords_per_minute = -1.;
  2722. X
  2723. X    while ((ch = getopt (argc, argv, "F:w:lbamf:g:v:tTdesp:riIcM:E:")) != EOF)
  2724. X    switch ((char) ch)
  2725. X    {
  2726. X    case 'i':
  2727. X        typeaway = 1;
  2728. X        break;
  2729. X    case 'I':
  2730. X        typeaway = LETMESEE;
  2731. X        break;
  2732. X    case 'r':
  2733. X        randomletters = 1;
  2734. X        break;
  2735. X    case 'c':
  2736. X        noticebad = 1;
  2737. X        break;
  2738. X    case 'e':
  2739. X        fancyending = 0;
  2740. X        break;
  2741. X    case 'T':
  2742. X        testing = 1;
  2743. X        showtesting = 1;
  2744. X        break;
  2745. X    case 't':
  2746. X        testing = 1;
  2747. X        break;
  2748. X    case 's':
  2749. X        charbychar = 1;
  2750. X        testing = 1;
  2751. X        break;
  2752. X    case 'p':
  2753. X        charbychar = 1;
  2754. X        testing = 1;
  2755. X        sscanf (optarg, "%d", &tryagaincount);
  2756. X        break;
  2757. X    case 'M':
  2758. X        testing = 1;
  2759. X        sscanf (optarg, "%d", &max_behindness);
  2760. X        if (max_behindness < 1)
  2761. X        max_behindness = 0;
  2762. X        break;
  2763. X    case 'E':
  2764. X        testing = 1;
  2765. X        sscanf (optarg, "%d", &error_threshold);
  2766. X        if (error_threshold < error_floor)
  2767. X        error_floor = error_threshold;
  2768. X        break;
  2769. X    case 'd':
  2770. X        dynamicspeed = 1;
  2771. X        break;
  2772. X    case 'w':
  2773. X        sscanf (optarg, "%f", &words_per_minute);
  2774. X        break;
  2775. X    case 'F':
  2776. X        sscanf (optarg, "%f", &fwords_per_minute);
  2777. X        break;
  2778. X    case 'l':
  2779. X        showletters = 1;
  2780. X        break;
  2781. X    case 'b':
  2782. X        wordsbefore = 1;
  2783. X        break;
  2784. X    case 'a':
  2785. X        wordsafter = 1;
  2786. X        break;
  2787. X    case 'm':
  2788. X        showmorse = 1;
  2789. X        break;
  2790. X    case 'f':
  2791. X        sscanf (optarg, "%f", &frequency1);
  2792. X        break;
  2793. X    case 'g':
  2794. X        sscanf (optarg, "%f", &frequency2);
  2795. X        break;
  2796. X    case 'v':
  2797. X        sscanf (optarg, "%f", &volume);
  2798. X        if (volume < 0.)
  2799. X        volume = 0.;
  2800. X        if (volume > 1.)
  2801. X        volume = 1.;
  2802. X        break;
  2803. X    default:
  2804. X        fprintf (stderr, "Type \"morse\" without arguments to get self-doc!\n");
  2805. X        exit (1);
  2806. X        break;
  2807. X    }
  2808. X    argc -= optind;
  2809. X    argv += optind;
  2810. X
  2811. X    if (fwords_per_minute <= 0.)
  2812. X    fwords_per_minute = words_per_minute;
  2813. X    new_words_per_minute ();
  2814. X
  2815. X    frequency = frequency1;
  2816. X
  2817. X    if (BeepInit () != 0)
  2818. X    {
  2819. X    fprintf (stderr, "Can't access speaker.\n");
  2820. X    exit (1);
  2821. X    }
  2822. X
  2823. X    signal (SIGINT, die);
  2824. X    signal (SIGTERM, die);
  2825. X    signal (SIGQUIT, die);
  2826. X    signal (SIGTSTP, suspend);
  2827. X
  2828. X    if (testing || typeaway)
  2829. X    {
  2830. X    openterminal ();
  2831. X    }
  2832. X
  2833. X/*
  2834. X * Do .25 seconds of silence initially to give the workstation time to
  2835. X * get settled after the stress of starting this program and opening
  2836. X * up everything.
  2837. X */
  2838. X    tone (frequency, .25, 0.);
  2839. X    toneflush ();
  2840. X
  2841. X    if (typeaway)
  2842. X    {
  2843. X    testing = 0;
  2844. X    showtesting = 0;
  2845. X    charbychar = 0;
  2846. X    wordsbefore = 0;
  2847. X    wordsafter = 0;
  2848. X    randomletters = 0;
  2849. X
  2850. X    notdoneyet = 1;
  2851. X
  2852. X    while (notdoneyet)
  2853. X    {
  2854. X        pollyou ();
  2855. X
  2856. X        for (jj = 0; jj < yourlength; jj++)
  2857. X        {
  2858. X        yourchar = yourstring[(yourpointer - yourlength + 1 + jj + TESTBUFSZ) % TESTBUFSZ];
  2859. X
  2860. X        /* Control-D: finished */
  2861. X        if (yourchar == (int) '\004')
  2862. X        {
  2863. X            toneflush ();
  2864. X            notdoneyet = 0;
  2865. X            break;
  2866. X        }
  2867. X
  2868. X        if (isspace (yourchar))
  2869. X        {
  2870. X            if (showletters)
  2871. X            {
  2872. X            toneflush ();
  2873. X            printf ("%c", yourchar);
  2874. X            fflush (stdout);
  2875. X            }
  2876. X
  2877. X            tone (frequency, inter_word_time, 0.);
  2878. X
  2879. X            continue;
  2880. X        }
  2881. X
  2882. X        morse (yourchar);
  2883. X        }
  2884. X        yourlength -= jj;
  2885. X    }
  2886. X    }
  2887. X    else if (randomletters)
  2888. X    {
  2889. X    SEEDRANDOM (time (NULL));
  2890. X    randexp = 1. / (1. - 1. / (float) (RANDWORDLEN));
  2891. X    linepos = 0;
  2892. X    while (1)
  2893. X    {
  2894. X        dowords (randomletter ());
  2895. X        linepos++;
  2896. X
  2897. X        /* Knock a few bits off the top so we're sure it won't overflow */
  2898. X        /* Shift a few bits because the lower bits stink */
  2899. X        /* Add in the time so it doesn't repeat from run to run */
  2900. X        randnum = (float) (
  2901. X                   ((RANDOM () >> 9) + (long) (time (NULL)) >> 4)
  2902. X                   & 0x00FFFFFF);
  2903. X        randnum = randnum - randexp * (int) (randnum / randexp);
  2904. X        if (randnum >= 1.)
  2905. X        if (linepos >= RANLINELENGTH)
  2906. X        {
  2907. X            dowords ((int) '\n');
  2908. X            linepos = 0;
  2909. X        }
  2910. X        else
  2911. X        {
  2912. X            dowords ((int) ' ');
  2913. X            linepos++;
  2914. X        }
  2915. X    }
  2916. X    }
  2917. X    else
  2918. X    {
  2919. X    if (*argv)
  2920. X    {
  2921. X        firsttime = 1;
  2922. X
  2923. X        do
  2924. X        {
  2925. X        if (!firsttime)
  2926. X        {
  2927. X            dowords ((int) ' ');
  2928. X        }
  2929. X        else
  2930. X            firsttime = 0;
  2931. X
  2932. X        for (p = *argv; *p; ++p)
  2933. X            dowords ((int) *p);
  2934. X        } while (*++argv);
  2935. X    }
  2936. X    else
  2937. X    {
  2938. X        while ((ch = getchar ()) != EOF)
  2939. X        dowords (ch);
  2940. X    }
  2941. X    }
  2942. X
  2943. X    if (fancyending)
  2944. X    dowords (EOF);
  2945. X    else
  2946. X    dowords (SILENTEOF);
  2947. X
  2948. X    fflush (stdout);
  2949. X
  2950. X    if (testing)
  2951. X    {
  2952. X    /*
  2953. X     * WE'RE completely done, and YOU aren't! Force catch up. (Note if
  2954. X     * charbychar = YES we won't get here, since we're always caught up
  2955. X     * after each character as it comes out.)
  2956. X     */
  2957. X    while (testlength > 0)
  2958. X    {
  2959. X        tone (frequency, catchup_time, 0.);
  2960. X        toneflush ();
  2961. X        testterminal ();
  2962. X    }
  2963. X    }
  2964. X
  2965. X    /* Just to be sure! */
  2966. X    toneflush ();
  2967. X
  2968. X    if (showmorse || wordsbefore || wordsafter || showletters || showtesting)
  2969. X    printf ("\n");
  2970. X    fflush (stdout);
  2971. X
  2972. X    if (testing)
  2973. X    report ();
  2974. X
  2975. X/* If you make any mistakes exit with a return code! */
  2976. X    cleanup ();
  2977. X    return (totalmisscount > 0);
  2978. X}
  2979. X
  2980. Xnew_words_per_minute ()
  2981. X{
  2982. Xfloat           wtick, ftick, tick;
  2983. X
  2984. X    tick = 60. / (words_per_minute * 50);
  2985. X
  2986. X    /*
  2987. X     * In the limit as wpm goes past fwpm, Farnsworth becomes kosher PARIS
  2988. X     */
  2989. X    if (fwords_per_minute <= words_per_minute)
  2990. X    ftick = 60. / (words_per_minute * 50);
  2991. X    else
  2992. X    ftick = 60. / (fwords_per_minute * 50);
  2993. X
  2994. X    wtick = (50. * tick - 31. * ftick) / 19.;
  2995. X
  2996. X    /*
  2997. X     * This time is used when the computer is waiting on you to hit a key; it
  2998. X     * is useful to scale the granularity with the real overrall words per
  2999. X     * minute. This also serves as a measuring rod to see if you are
  3000. X     * responding "fast enough". If you are too slow, then obviously you are
  3001. X     * having trouble with that character, and should be given it more OFTEN.
  3002. X     * Heh heh heh...
  3003. X     */
  3004. X    catchup_time = tick;
  3005. X
  3006. X    /*
  3007. X     * Things between characters and words go at the "remainder" speed,
  3008. X     * whatever space you need to make the sped-up Farnsworth characters come
  3009. X     * out with the correct overall words per minute.
  3010. X     */
  3011. X    inter_char_time = wtick * 3.;
  3012. X    inter_word_time = wtick * 7.;
  3013. X
  3014. X    /* Things within the character go at the Farnsworth speed */
  3015. X    intra_char_time = ftick;
  3016. X    dot_time = ftick;
  3017. X    dash_time = ftick * 3.;
  3018. X}
  3019. X
  3020. Xstatic int      tryingagain = 0, slowpoke = 0;
  3021. X
  3022. Xdowords (c)
  3023. X    int             c;
  3024. X{
  3025. Xstatic int      wordc = 0;
  3026. Xstatic char     word[MAXWORDLEN];
  3027. Xchar           *wordp;
  3028. Xint             ii;
  3029. Xint             againcount;
  3030. Xint             are_we_repeating;
  3031. X
  3032. X/*
  3033. X * If a word gets too long, just cut it off by inserting a space.
  3034. X * Just call ourselves with the character we wish we'd gotten...
  3035. X */
  3036. X    if (wordc == MAXWORDLEN - 1 && !(isspace (c) || c == EOF || c == SILENTEOF || c == FREQU_TOGGLE))
  3037. X    dowords ((int) ' ');
  3038. X
  3039. X    if (isspace (c) || c == EOF || c == SILENTEOF || c == FREQU_TOGGLE)
  3040. X    {
  3041. X    if (wordc > 0)
  3042. X    {
  3043. X        word[wordc] = '\0';
  3044. X
  3045. X/*
  3046. X * We have just read in a new complete word from the input, (hopefully)
  3047. X * during the time of an inter-word space minus an inter-char space.
  3048. X * Now let's go back and see what happened with the PREVIOUS word,
  3049. X * the one that we had just finished playing. Did the user keep
  3050. X * up with us?
  3051. X */
  3052. X#ifdef DEBUG
  3053. X        fprintf (stderr, " [%d] ", behindness);
  3054. X#endif
  3055. X        if (testing && dynamicspeed && !charbychar)
  3056. X        {
  3057. X        /*
  3058. X         * (If charbychar then behindness is ALWAYS 0 at this
  3059. X         * point...)
  3060. X         */
  3061. X        if (behindness == 0)
  3062. X        {
  3063. X            /* You're a speed demon! Speed up a bit, then! */
  3064. X            words_per_minute *= ALITTLEFASTER;
  3065. X            new_words_per_minute ();
  3066. X        }
  3067. X        else if (behindness > WAYBEHIND)
  3068. X        {
  3069. X            /* You're way behind! Slow way down. */
  3070. X            words_per_minute /= ALOTSLOWER;
  3071. X            new_words_per_minute ();
  3072. X        }
  3073. X        else if (behindness > BEHIND)
  3074. X        {
  3075. X            /* You're behind! Slow down a bit. */
  3076. X            words_per_minute /= ALITTLESLOWER;
  3077. X            new_words_per_minute ();
  3078. X        }
  3079. X        }
  3080. X
  3081. X
  3082. X/*
  3083. X * If the user was WAY too far behind stop and catch up with
  3084. X * the "new" word as the first one.
  3085. X */
  3086. X        if (testing && (behindness > TOOFARBEHIND || helpmeflag))
  3087. X        {
  3088. X        if (helpmeflag)
  3089. X            printf ("\nOK, let's restart.\n");
  3090. X        else
  3091. X            printf ("\nYou are too far behind! Let's restart.\n");
  3092. X        fflush (stdout);
  3093. X
  3094. X        toneflush ();
  3095. X
  3096. X        /* Flush the keyboard buffer */
  3097. X        pollyou ();
  3098. X
  3099. X        /* Forget the past */
  3100. X        helpmeflag = 0;
  3101. X        behindness = 0;
  3102. X        testlength = 0;
  3103. X        yourlength = 0;
  3104. X
  3105. X        /* Give the user a little rest. */
  3106. X        sleep (2);
  3107. X        printf ("\nWPM now %d\n", (int) (words_per_minute + .5));
  3108. X        fflush (stdout);
  3109. X        sleep (2);
  3110. X        printf ("\nREADY?\n");
  3111. X        fflush (stdout);
  3112. X        sleep (1);
  3113. X        printf ("\nSET\n");
  3114. X        fflush (stdout);
  3115. X        sleep (1);
  3116. X        printf ("\nGO!\n");
  3117. X        fflush (stdout);
  3118. X        }
  3119. X
  3120. X/*
  3121. X * Start treating the new word.
  3122. X */
  3123. X        if (wordsbefore)
  3124. X        {
  3125. X        /* Try to keep your out-of-sync text from getting swirled in */
  3126. X        if (showtesting)
  3127. X            printf ("\n");
  3128. X
  3129. X        printf ("%s", word);
  3130. X
  3131. X        if (showmorse || showletters || wordsafter || showtesting)
  3132. X        {
  3133. X            printf ("  ");
  3134. X            for (ii = 0; ii < 16 - (wordc + 2); ii++)
  3135. X            {
  3136. X            printf (" ");
  3137. X            }
  3138. X        }
  3139. X
  3140. X        fflush (stdout);
  3141. X        }
  3142. X
  3143. X        if (testing && charbychar)
  3144. X        {
  3145. X        againcount = 0;
  3146. X        }
  3147. X
  3148. X        for (wordp = word; *wordp != '\0'; wordp++)
  3149. X        {
  3150. X        tryingagain = 0;
  3151. X
  3152. X    tryagain:
  3153. X        if (testing && !tryingagain && !showletters &&
  3154. X            error_threshold < MAX_ERROR_THRESHOLD &&
  3155. X            errorlog[(int) *wordp] > error_threshold)
  3156. X        {
  3157. X            toneflush ();
  3158. X            /* Give them a quick hint */
  3159. X            printf ("[%c]", *wordp);
  3160. X            fflush (stdout);
  3161. X
  3162. X            morse (*wordp);
  3163. X
  3164. X            toneflush ();
  3165. X            if (!showmorse)
  3166. X            {
  3167. X            /* Erase the hint */
  3168. X            printf ("\b\b\b   \b\b\b", *wordp);
  3169. X            fflush (stdout);
  3170. X            }
  3171. X        }
  3172. X        else
  3173. X        {
  3174. X            morse (*wordp);
  3175. X        }
  3176. X
  3177. X        if (testing)
  3178. X        {
  3179. X            if (charbychar)
  3180. X            {
  3181. X            toneflush ();
  3182. X            /* Force catchup */
  3183. X            slowpoke = 0;
  3184. X            while (behindness > 0)
  3185. X            {
  3186. X                if (testterminal () && tryagaincount > 0)
  3187. X                {
  3188. X                /*
  3189. X                 * OOPS! They got it WRONG! MAKE THEM TRY
  3190. X                 * AGAIN!
  3191. X                 */
  3192. X                printf ("Try again.\n");
  3193. X                /*
  3194. X                 * Yeah I know gotos are inelegant but I
  3195. X                 * don't feel like figuring out the "elegant"
  3196. X                 * way to do this right now.
  3197. X                 */
  3198. X                againcount = tryagaincount - 1;
  3199. X                tryingagain = 1;
  3200. X                goto tryagain;
  3201. X                }
  3202. X                else
  3203. X                {
  3204. X                /*
  3205. X                 * They got it right, or they didn't answer
  3206. X                 * yet.
  3207. X                 */
  3208. X                if (behindness > 0)
  3209. X                {
  3210. X                    /*
  3211. X                     * They are STILL thinking, the
  3212. X                     * slowpokes. Wait a bit before trying
  3213. X                     * again.
  3214. X                     */
  3215. X                    tone (frequency, catchup_time, 0.);
  3216. X                    /*
  3217. X                     * Keep track of how long they're taking
  3218. X                     * to answer!
  3219. X                     */
  3220. X                    if (slowpoke < SLOWPOKEMAX)
  3221. X                    slowpoke++;
  3222. X                    toneflush ();
  3223. X                }
  3224. X                else if (dynamicspeed && !slowpoke && !tryingagain)
  3225. X                {
  3226. X                    /*
  3227. X                     * They got it right without errors the
  3228. X                     * first time and we didn't have to wait
  3229. X                     * for them! A speed demon! Speed up a
  3230. X                     * bit, then!
  3231. X                     */
  3232. X                    words_per_minute *= ALITTLEFASTER;
  3233. X                    new_words_per_minute ();
  3234. X                }
  3235. X                }
  3236. X            }
  3237. X
  3238. X            /* Insufficient penance? */
  3239. X            if (againcount > 0)
  3240. X            {
  3241. X                againcount--;
  3242. X                goto tryagain;
  3243. X            }
  3244. X            }
  3245. X            else
  3246. X            {
  3247. X            testterminal ();
  3248. X            /*
  3249. X             * Stop if we get more than max_behindness ahead.
  3250. X             * max_behindness == 0 means don't worry about them,
  3251. X             * they can be as far behind as they want and we
  3252. X             * won't stop!
  3253. X             */
  3254. X            if (max_behindness > 0)
  3255. X            {
  3256. X                are_we_repeating = 0;
  3257. X                while (behindness >= max_behindness)
  3258. X                {
  3259. X#ifdef DEBUG
  3260. X                fprintf (stderr, " (%d) ", behindness);
  3261. X#endif
  3262. X                if (are_we_repeating)
  3263. X                {
  3264. X                    /*
  3265. X                     * Pause for a bit so we don't loop too
  3266. X                     * fast
  3267. X                     */
  3268. X                    tone (frequency, catchup_time, 0.);
  3269. X                }
  3270. X                else
  3271. X                {
  3272. X                    are_we_repeating = 1;
  3273. X                }
  3274. X                /* Finish playing whatever we're playing */
  3275. X                toneflush ();
  3276. X                /* And give them another chance */
  3277. X                testterminal ();
  3278. X                }
  3279. X            }
  3280. X            }
  3281. X        }
  3282. X        }
  3283. X
  3284. X        toneflush ();
  3285. X        if (testing)
  3286. X        testterminal ();
  3287. X
  3288. X        if (wordsafter)
  3289. X        {
  3290. X        printf (" (%s)", word);
  3291. X        }
  3292. X
  3293. X        if (wordsbefore || wordsafter || showmorse)
  3294. X        printf ("\n");
  3295. X        else if (showletters || showtesting)
  3296. X        {
  3297. X        if (c != EOF && c != SILENTEOF && c != FREQU_TOGGLE)
  3298. X        {
  3299. X            if (showletters)
  3300. X            printf ("%c", c);
  3301. X
  3302. X            if (showtesting)
  3303. X            testaddchar (c);
  3304. X        }
  3305. X        }
  3306. X
  3307. X/*
  3308. X * WHEW! FINISHED QUEUEING THE WORD FOR PLAYING!
  3309. X * Now finish up all the other sundry details...
  3310. X */
  3311. X
  3312. X        /* Flush the output printing queue... */
  3313. X        fflush (stdout);
  3314. X        /*
  3315. X         * Pause for a bit; this gives the user a sporting chance at
  3316. X         * catching up with us.
  3317. X         */
  3318. X        tone (frequency, SPORTING_RATIO * inter_char_time, 0.);
  3319. X        toneflush ();
  3320. X        /* Start sounding an inter-word space */
  3321. X        tone (frequency, inter_word_time - SPORTING_RATIO * inter_char_time, 0.);
  3322. X
  3323. X        /* While that silence is playing check if the user has caught up. */
  3324. X        if (testing)
  3325. X        testterminal ();
  3326. X
  3327. X        /* We finished this word; reset the word character count */
  3328. X        wordc = 0;
  3329. X    }
  3330. X    else if (!(wordsbefore || wordsafter || showmorse)
  3331. X         &&
  3332. X         (showletters || showtesting))
  3333. X    {
  3334. X        if (c != EOF && c != SILENTEOF && c != FREQU_TOGGLE)
  3335. X        {
  3336. X        if (showletters)
  3337. X            printf ("%c", c);
  3338. X
  3339. X        if (showtesting)
  3340. X            testaddchar (c);
  3341. X        }
  3342. X    }
  3343. X
  3344. X    if (c == EOF)
  3345. X    {
  3346. X        morse (EOF);
  3347. X        toneflush ();
  3348. X    }
  3349. X    else if (c == SILENTEOF)
  3350. X    {
  3351. X        toneflush ();
  3352. X    }
  3353. X    else if (c == FREQU_TOGGLE)
  3354. X    {
  3355. X        /* Switch to the other frequency */
  3356. X        /* (Won't work from keyboard, only from a file.) */
  3357. X        whichfrequ = 1 - whichfrequ;
  3358. X        switch (whichfrequ)
  3359. X        {
  3360. X        case 1:
  3361. X        frequency = frequency2;
  3362. X        break;
  3363. X        case 0:
  3364. X        default:
  3365. X        frequency = frequency1;
  3366. X        break;
  3367. X        }
  3368. X    }
  3369. X    }
  3370. X    else
  3371. X    {
  3372. X    word[wordc++] = c;
  3373. X    }
  3374. X}
  3375. X
  3376. X/*
  3377. X * Don't try to test the person DURING the call into morse!
  3378. X */
  3379. Xmorse (c)
  3380. X    int             c;
  3381. X{
  3382. X    if (showletters)
  3383. X    {
  3384. X    if (c == EOF)
  3385. X        printf ("EOT");
  3386. X    else if (c == '.' && showmorse)
  3387. X        printf ("PERIOD");
  3388. X    else if (c == '=' && showmorse)
  3389. X        printf ("BREAK");
  3390. X    else
  3391. X        printf ("%c", c);
  3392. X
  3393. X    fflush (stdout);
  3394. X    }
  3395. X
  3396. X    if (isalpha (c))
  3397. X    {
  3398. X    if (testing)
  3399. X        testaddchar (c - (isupper (c) ? 'A' : 'a') + 'a');
  3400. X    show (code[c - (isupper (c) ? 'A' : 'a') + 'a']);
  3401. X    }
  3402. X    else if (c == EOF)
  3403. X    {
  3404. X    show (code[(int) '@']);
  3405. X    }
  3406. X    else if (code[c] != NULL)
  3407. X    {
  3408. X    if (testing)
  3409. X        testaddchar (c);
  3410. X    show (code[c]);
  3411. X    }
  3412. X    else
  3413. X    {
  3414. X    /* Oops! This letter is junk! */
  3415. X
  3416. X    if (noticebad)
  3417. X    {
  3418. X        if (showletters)
  3419. X        {
  3420. X        fflush (stdout);
  3421. X        }
  3422. X
  3423. X        /* Simulate a stumble */
  3424. X        tone (frequency, 2. * inter_word_time, 0.);
  3425. X        toneflush ();
  3426. X    }
  3427. X
  3428. X    if (showletters)
  3429. X    {
  3430. X        /* Wipe out what we just printed */
  3431. X        fflush (stdout);
  3432. X        printf ("\b");
  3433. X        printf (" ");
  3434. X        printf ("\b");
  3435. X        fflush (stdout);
  3436. X    }
  3437. X
  3438. X    if (noticebad)
  3439. X    {
  3440. X        if (showletters)
  3441. X        {
  3442. X        /* And replace it with an error message */
  3443. X        printf ("*UNKNOWN_CHARACTER*");
  3444. X        fflush (stdout);
  3445. X        }
  3446. X
  3447. X        /* Give the error call */
  3448. X        show ("........");
  3449. X
  3450. X        /* Regroup */
  3451. X        tone (frequency, inter_word_time, 0.);
  3452. X    }
  3453. X    }
  3454. X
  3455. X    if (showmorse)
  3456. X    printf (" ");
  3457. X    fflush (stdout);
  3458. X    toneflush ();
  3459. X    tone (frequency, inter_char_time - intra_char_time, 0.);
  3460. X}
  3461. X
  3462. X
  3463. X/*
  3464. X * Don't try to test the person WHILE doing dots and dashes!
  3465. X */
  3466. Xshow (s)
  3467. X    char           *s;
  3468. X{
  3469. Xchar            c;
  3470. X
  3471. X    while ((c = *s++) != '\0')
  3472. X    {
  3473. X    tone (frequency, intra_char_time, 0.);
  3474. X
  3475. X#ifdef FLUSHCODE
  3476. X    if (showmorse)
  3477. X        toneflush ();
  3478. X#endif
  3479. X
  3480. X    switch (c)
  3481. X    {
  3482. X    case '.':
  3483. X        tone (frequency, dot_time, volume);
  3484. X        break;
  3485. X    case '-':
  3486. X        tone (frequency, dash_time, volume);
  3487. X        break;
  3488. X    }
  3489. X
  3490. X    if (showmorse)
  3491. X    {
  3492. X        printf ("%c", c);
  3493. X        fflush (stdout);
  3494. X#ifdef FLUSHCODE
  3495. X        toneflush ();
  3496. X#endif
  3497. X    }
  3498. X    }
  3499. X}
  3500. X
  3501. X/*
  3502. X * This only gets passed valid characters: ones
  3503. X * that have a morse code associated with them
  3504. X * or ones for which isspace(c) is true.
  3505. X */
  3506. Xtestaddchar (c)
  3507. X    char            c;
  3508. X{
  3509. X    testpointer = (testpointer + 1) % TESTBUFSZ;
  3510. X    teststring[testpointer] = c;
  3511. X#ifdef DEBUG
  3512. X    fprintf (stderr, " (%c,%d,%d) ", c, testlength, behindness);
  3513. X#endif
  3514. X    testlength++;
  3515. X    if (testlength > TESTBUFSZ)
  3516. X    {
  3517. X    fprintf (stderr, "\n\nInput buffer queue overflow! Make TESTBUFSZ bigger!\n");
  3518. X    fprintf (stderr, "(Or don't fall so far behind)\n");
  3519. X
  3520. X    die ();
  3521. X    }
  3522. X
  3523. X/*
  3524. X * Since you are never asked to type spaces (you can type them if
  3525. X * you want, but they are ignored) spaces in the input file don't
  3526. X * count against your "behindness".
  3527. X */
  3528. X    if (!isspace (c))
  3529. X    behindness++;
  3530. X}
  3531. X
  3532. Xyouraddchar (c)
  3533. X    char            c;
  3534. X{
  3535. X    yourpointer = (yourpointer + 1) % TESTBUFSZ;
  3536. X    yourstring[yourpointer] = c;
  3537. X#ifdef DEBUG
  3538. X    fprintf (stderr, " <%c,%d> ", c, yourlength);
  3539. X#endif
  3540. X    yourlength++;
  3541. X    if (yourlength > TESTBUFSZ)
  3542. X    {
  3543. X    fprintf (stderr, "\n\nKeyboard typeahead buffer queue overflow! Make TESTBUFSZ bigger!\n");
  3544. X    fprintf (stderr, "(Or don't type so far ahead... how did you expect to get them right anyway?)\n");
  3545. X
  3546. X    die ();
  3547. X    }
  3548. X}
  3549. X
  3550. Xpollyou ()
  3551. X{
  3552. Xint             ii, num;
  3553. Xchar           *string;
  3554. X
  3555. X    num = readterminal (&string);
  3556. X
  3557. X    for (ii = 0; ii < num; ii++)
  3558. X    youraddchar (string[ii]);
  3559. X}
  3560. X
  3561. Xint
  3562. Xtestterminal ()
  3563. X{
  3564. Xint             testinc, yourinc;
  3565. Xint             correctchar, yourchar, yourcharnocase;
  3566. Xint             errorcount;
  3567. X
  3568. X    errorcount = 0;
  3569. X
  3570. X/*
  3571. X * There is nothing in the input file queue right now,
  3572. X * so we can't process any of your keystrokes.
  3573. X * Defer processing until we can catch up with YOU!
  3574. X */
  3575. X    if (testlength == 0)
  3576. X    return errorcount;
  3577. X
  3578. X    /* We're ready for you; but are you ready for us? */
  3579. X    pollyou ();
  3580. X
  3581. X/*
  3582. X * Process your entries and the input queue entries in parallel
  3583. X */
  3584. X    if (yourlength > 0 && testlength > 0)
  3585. X    {
  3586. X    for (testinc = 0, yourinc = 0;
  3587. X         testinc < testlength && yourinc < yourlength;
  3588. X         testinc++, yourinc++)
  3589. X    {
  3590. X        correctchar = teststring[(testpointer - testlength + 1 + testinc + TESTBUFSZ) % TESTBUFSZ];
  3591. X
  3592. X        /*
  3593. X         * The latter half of this if shouldn't be necessary, but just in
  3594. X         * case...
  3595. X         */
  3596. X        if (isspace (correctchar) || code[correctchar] == NULL)
  3597. X        {
  3598. X        if (showtesting)
  3599. X        {
  3600. X            printf ("%c", correctchar);
  3601. X            fflush (stdout);
  3602. X        }
  3603. X
  3604. X        /* White space doesn't count for "behindness" */
  3605. X        behindness++;
  3606. X        /* The _other_ pointer wasn't used; don't increment it. */
  3607. X        yourinc--;
  3608. X
  3609. X        /* Short circuit the loop */
  3610. X        continue;
  3611. X        }
  3612. X
  3613. X
  3614. X        yourchar = yourstring[(yourpointer - yourlength + 1 + yourinc + TESTBUFSZ) % TESTBUFSZ];
  3615. X        if (isalpha (yourchar))
  3616. X        yourcharnocase = yourchar - (isupper (yourchar) ? 'A' : 'a') + 'a';
  3617. X        else
  3618. X        yourcharnocase = yourchar;
  3619. X
  3620. X        /* Did you type something rude? If so, just ignore it. */
  3621. X        if (isspace (yourchar) || code[yourcharnocase] == NULL)
  3622. X        {
  3623. X        /* ESCAPE: dump status info */
  3624. X        /* Control-D: dump status info and then bye bye */
  3625. X        /* Control-H: force restart */
  3626. X        if (yourchar == '\033' || yourchar == (int) '\004')
  3627. X        {
  3628. X            report ();
  3629. X
  3630. X            if (yourchar == (int) '\004')
  3631. X            die ();
  3632. X        }
  3633. X        else if (yourchar == '\b')
  3634. X        {
  3635. X            helpmeflag = 1;
  3636. X        }
  3637. X
  3638. X        /* The _other_ pointer wasn't used; don't increment it. */
  3639. X        testinc--;
  3640. X        /* Short circuit the loop */
  3641. X        continue;
  3642. X        }
  3643. X
  3644. X        if (yourcharnocase != correctchar)
  3645. X        {
  3646. X        errorcount++;
  3647. X        totalmisscount++;
  3648. X
  3649. X        /*
  3650. X         * Record that you are having trouble with these.
  3651. X         */
  3652. X        errorlog[correctchar]++;
  3653. X        if (code[yourcharnocase] != NULL &&
  3654. X            errorlog[yourcharnocase] < MAX_ERROR_THRESHOLD)
  3655. X            errorlog[yourcharnocase]++;
  3656. X
  3657. X        printf ("\n\007%c (%s) for %c (%s)\n",
  3658. X            yourchar, code[yourcharnocase],
  3659. X            correctchar, code[correctchar]);
  3660. X        fflush (stdout);
  3661. X
  3662. X        if (charbychar)
  3663. X        {
  3664. X            /* Give them a bit of time to think about their error */
  3665. X            tone (frequency, inter_word_time, 0.);
  3666. X            toneflush ();
  3667. X        }
  3668. X        if (dynamicspeed && !charbychar)
  3669. X        {
  3670. X            /*
  3671. X             * Slow down. Doesn't make sense to slow down for errors,
  3672. X             * though, if you've got all the time you want to think
  3673. X             * about each one.
  3674. X             */
  3675. X            words_per_minute /= ERRORSLOWER;
  3676. X            new_words_per_minute ();
  3677. X        }
  3678. X        if (randomletters && !tryingagain)
  3679. X        {
  3680. X            /*
  3681. X             * Ask ones that confused you more often!
  3682. X             */
  3683. X            if (code[yourcharnocase] != NULL)
  3684. X            {
  3685. X            randomfactor[yourcharnocase] += (3 * RANDOMINCWORSE / 2);
  3686. X            if (randomfactor[yourcharnocase] > RANDOMMAX)
  3687. X                randomfactor[yourcharnocase] = RANDOMMAX;
  3688. X            }
  3689. X
  3690. X            randomfactor[correctchar] += RANDOMINCWORSE * 2;
  3691. X            if (randomfactor[correctchar] > RANDOMMAX)
  3692. X            randomfactor[correctchar] = RANDOMMAX;
  3693. X        }
  3694. X        }
  3695. X        else
  3696. X        {
  3697. X        /*
  3698. X         * Record that you got this right.
  3699. X         */
  3700. X        if (!tryingagain)
  3701. X        {
  3702. X            totalhitcount++;
  3703. X            if (errorlog[correctchar] > error_floor)
  3704. X            errorlog[correctchar]--;
  3705. X        }
  3706. X
  3707. X        if (showtesting)
  3708. X        {
  3709. X            printf ("%c", yourchar);
  3710. X            fflush (stdout);
  3711. X        }
  3712. X
  3713. X        if (randomletters && !tryingagain)
  3714. X        {
  3715. X            if (slowpoke == SLOWPOKEMAX)
  3716. X            {
  3717. X            printf ("\nNice to have you back again, I was getting bored!\n");
  3718. X            }
  3719. X            else if (slowpoke >= SLOWPOKE * 3)
  3720. X            {
  3721. X            /*
  3722. X             * Did you take too long thinking about it? If so,
  3723. X             * you probably need to be asked this one more
  3724. X             * often...
  3725. X             */
  3726. X            randomfactor[correctchar] += (3 * RANDOMINCWORSE / 2);
  3727. X            if (randomfactor[correctchar] > RANDOMMAX)
  3728. X                randomfactor[correctchar] = RANDOMMAX;
  3729. X
  3730. X            /*
  3731. X             * Hits this slow shouldn't count! You were obviously
  3732. X             * just guessing! (But it doesn't count as an error
  3733. X             * either.)
  3734. X             */
  3735. X            totalhitcount--;
  3736. X            }
  3737. X            else if (slowpoke > FASTPOKE)
  3738. X            {
  3739. X            randomfactor[correctchar] +=
  3740. X             (slowpoke * RANDOMINCWORSE) / (2 * SLOWPOKE);
  3741. X            if (randomfactor[correctchar] > RANDOMMAX)
  3742. X                randomfactor[correctchar] = RANDOMMAX;
  3743. X            }
  3744. X            else if (slowpoke <= (FASTPOKE / 2))
  3745. X            {
  3746. X            /*
  3747. X             * Ask ones that you quickly answer correctly less
  3748. X             * often!
  3749. X             */
  3750. X            randomfactor[correctchar] -= (3 * RANDOMINCBETTER / 2);
  3751. X            /*
  3752. X             * Don't let randomfactor hit 0, or you'll NEVER be
  3753. X             * asked this one AGAIN!
  3754. X             */
  3755. X            if (randomfactor[correctchar] < 1)
  3756. X                randomfactor[correctchar] = 1;
  3757. X            }
  3758. X            else if (slowpoke <= FASTPOKE)
  3759. X            {
  3760. X            randomfactor[correctchar] -= (RANDOMINCBETTER / 2);
  3761. X            if (randomfactor[correctchar] < 1)
  3762. X                randomfactor[correctchar] = 1;
  3763. X            }
  3764. X        }
  3765. X        }
  3766. X
  3767. X    }
  3768. X    testlength -= testinc;
  3769. X    behindness -= testinc;
  3770. X    yourlength -= yourinc;
  3771. X    }
  3772. X
  3773. X/*
  3774. X * If there are some extra white space characters in the input queue
  3775. X * it's OK, we'll get to them next time or we'll clean them out at the
  3776. X * end.
  3777. X */
  3778. X    return errorcount;
  3779. X}
  3780. X
  3781. X
  3782. X/*----------------------------------------*/
  3783. X
  3784. Xtone (hertz, duration, amplitude)
  3785. X    float           hertz, duration, amplitude;
  3786. X{
  3787. X    Beep ((int) (duration * 1000), (int) (amplitude * 100), (int) hertz);
  3788. X}
  3789. X
  3790. X
  3791. Xtoneflush ()
  3792. X{
  3793. X    BeepWait ();
  3794. X}
  3795. X
  3796. X
  3797. X/*----------------------------------------*/
  3798. X
  3799. X#include <sys/ioctl.h>
  3800. X#include <fcntl.h>
  3801. X#ifdef USG
  3802. X#include <sys/termio.h>
  3803. Xstruct termio   oldtermgtty;
  3804. Xstruct termio   termgtty;
  3805. X#else
  3806. X#include <sys/file.h>
  3807. Xstruct sgttyb   oldtermgtty;
  3808. Xstruct sgttyb   termgtty;
  3809. X#endif
  3810. Xstatic char    *terminal = "/dev/tty";
  3811. Xstatic int      termfd;
  3812. Xstatic int      oldflgs, newflgs;
  3813. Xstatic int      termopen = 0;
  3814. X
  3815. Xopenterminal ()
  3816. X{
  3817. X    /* get parameters and open terminal */
  3818. X
  3819. X#ifdef USG
  3820. X    termfd = open (terminal, O_RDWR | O_NDELAY, 0);
  3821. X    ioctl (termfd, TCGETA, &termgtty);
  3822. X    oldtermgtty = termgtty;
  3823. X    if (typeaway != LETMESEE)
  3824. X    termgtty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
  3825. X    termgtty.c_lflag &= ~ICANON;
  3826. X    termgtty.c_cc[VMIN] = 1;
  3827. X    termgtty.c_cc[VTIME] = 0;
  3828. X    ioctl (0, TCSETAW, &termgtty);
  3829. X#else
  3830. X    termfd = open (terminal, O_RDWR, 0);
  3831. X    ioctl (termfd, TIOCGETP, &termgtty);
  3832. X    oldtermgtty = termgtty;
  3833. X    if (typeaway != LETMESEE)
  3834. X    termgtty.sg_flags &= ~ECHO;
  3835. X    termgtty.sg_flags |= CBREAK;
  3836. X    ioctl (termfd, TIOCSETP, &termgtty);
  3837. X    oldflgs = fcntl (termfd, F_GETFL);
  3838. X    newflgs = oldflgs | FNDELAY;
  3839. X#endif
  3840. X
  3841. X    termopen = 1;
  3842. X}
  3843. X
  3844. Xint
  3845. Xreadterminal (string)
  3846. X    char          **string;
  3847. X{
  3848. X/* This must be declared static! */
  3849. Xstatic char     line[TESTBUFSZ];
  3850. Xint             n;
  3851. X
  3852. X#ifndef USG
  3853. X    fcntl (termfd, F_SETFL, newflgs);
  3854. X#endif
  3855. X    n = read (termfd, line, sizeof (line) - 1);
  3856. X#ifndef USG
  3857. X    fcntl (termfd, F_SETFL, oldflgs);
  3858. X#endif
  3859. X
  3860. X    if (n > 0)
  3861. X    {
  3862. X    line[n] = '\0';
  3863. X    *string = line;
  3864. X    }
  3865. X    else
  3866. X    *string = NULL;
  3867. X
  3868. X    return n;
  3869. X}
  3870. X
  3871. Xcloseterminal ()
  3872. X{
  3873. X#ifdef USG
  3874. X    ioctl (termfd, TCSETAW, &oldtermgtty);
  3875. X#else
  3876. X    ioctl (termfd, TIOCSETP, &oldtermgtty);
  3877. X#endif
  3878. X    close (termfd);
  3879. X}
  3880. X
  3881. Xdie ()
  3882. X{
  3883. X    cleanup ();
  3884. X    exit (1);
  3885. X}
  3886. X
  3887. Xcleanup ()
  3888. X{
  3889. X    if (termopen)
  3890. X    closeterminal ();
  3891. X    BeepCleanup ();
  3892. X}
  3893. X
  3894. Xsuspend ()
  3895. X{
  3896. X    signal (SIGTSTP, suspend);
  3897. X    cleanup ();
  3898. X    kill (getpid (), SIGSTOP);
  3899. X    if (termopen)
  3900. X    openterminal ();
  3901. X    BeepResume ();
  3902. X}
  3903. X
  3904. X
  3905. X/*----------------------------------------*/
  3906. X
  3907. Xint
  3908. Xrandomletter ()
  3909. X{
  3910. Xint             ii;
  3911. Xint             sum, sum2;
  3912. Xlong            ranspot;
  3913. Xextern time_t   time ();
  3914. Xstatic int      lasttime = -1;
  3915. Xstatic long     norepeat;
  3916. X
  3917. X/*
  3918. X * This keeps the not-so-random random number generator from ignoring
  3919. X * certain characters forever!
  3920. X */
  3921. X    norepeat = ((long) time (NULL) / 31) % 17291;
  3922. X
  3923. X/*
  3924. X * All the usable letters get one unit riper.
  3925. X */
  3926. X    for (ii = 0; ii < TWOFIFTYSIX; ii++)
  3927. X    {
  3928. X    if (randomfactor[ii] > 0)
  3929. X    {
  3930. X#ifdef DEBUGG
  3931. X        fprintf (stderr, "%c: %d %d\n",
  3932. X             (char) ii, randomfactor[ii], randomripe[ii]);
  3933. X#endif
  3934. X        randomripe[ii]++;
  3935. X    }
  3936. X    }
  3937. X
  3938. X    sum = 0;
  3939. X    for (ii = 0; ii < TWOFIFTYSIX; ii++)
  3940. X    sum += (randomfactor[ii] + (int) (randomripe[ii] / RIPECOUNT));
  3941. X
  3942. X/*
  3943. X * The low bits of random aren't very random, I don't care WHAT
  3944. X * the manual claims.
  3945. X */
  3946. X    do
  3947. X    {
  3948. X    ranspot = ((RANDOM () >> 4) % sum + norepeat) % sum;
  3949. X
  3950. X    sum2 = 0;
  3951. X    for (ii = 0; ii < TWOFIFTYSIX - 1; ii++)
  3952. X    {
  3953. X        sum2 += (randomfactor[ii] + (int) (randomripe[ii] / RIPECOUNT));
  3954. X
  3955. X        if (sum2 > ranspot)
  3956. X        break;
  3957. X    }
  3958. X    /* Do it again if you got the same as last time! */
  3959. X    } while (ii == lasttime);
  3960. X
  3961. X    /* This one is FRESH again. */
  3962. X    randomripe[ii] = 0;
  3963. X    /* Remember for next time. */
  3964. X    lasttime = ii;
  3965. X
  3966. X    return ii;
  3967. X}
  3968. X
  3969. Xreport ()
  3970. X{
  3971. Xint             ii, jj, count;
  3972. Xfloat           sum;
  3973. Xint             randomstr[TWOFIFTYSIX];
  3974. Xextern int      rancomp ();
  3975. X
  3976. X    printf ("\nCurrent words per minute: %.1f\n", words_per_minute);
  3977. X
  3978. X    printf ("Total hits %d, misses %d", totalhitcount, totalmisscount);
  3979. X    if (totalmisscount > 0)
  3980. X    printf (", hit per miss ratio %.1f\n", (float) totalhitcount / (float) totalmisscount);
  3981. X    else
  3982. X    printf ("\n");
  3983. X
  3984. X    if (randomletters)
  3985. X    {
  3986. X    printf ("Most to least frequent choices:\n");
  3987. X    count = 0;
  3988. X    sum = 0.;
  3989. X    for (ii = 0; ii < TWOFIFTYSIX; ii++)
  3990. X    {
  3991. X        if (randomfactor[ii] > 0)
  3992. X        {
  3993. X        sum += (randomfactor[ii] + (randomripe[ii] / (float) RIPECOUNT));
  3994. X        randomstr[count] = ii;
  3995. X        count++;
  3996. X        }
  3997. X    }
  3998. X
  3999. X    qsort ((char *) randomstr, count, sizeof (randomstr[0]), rancomp);
  4000. X
  4001. X    for (ii = 0; ii < count; ii++)
  4002. X    {
  4003. X/*
  4004. X * Insert a space for each jump across an integer.
  4005. X * The normalization (count/sum) ensures that if all
  4006. X * letters were equally probable, they would all have value 1.
  4007. X * Since they are not generally equally probable, then 1 is just the average.
  4008. X * Thus the rightmost space in the printout marks where the average is.
  4009. X * Further left spaces separate off blocks of letters that are approximately
  4010. X * twice as probable as the average, three times, etc.
  4011. X */
  4012. X        if (ii > 0)
  4013. X        {
  4014. X        for (jj = 0; jj <
  4015. X             (int) (
  4016. X                (randomfactor[randomstr[ii - 1]] + (randomripe[randomstr[ii - 1]] / (float) RIPECOUNT))
  4017. X                * count / sum) -
  4018. X             (int) (
  4019. X                (randomfactor[randomstr[ii]] + (randomripe[randomstr[ii]] / (float) RIPECOUNT))
  4020. X                * count / sum);
  4021. X             jj++)
  4022. X            printf (" ");
  4023. X        }
  4024. X        printf ("%c", (char) randomstr[ii]);
  4025. X    }
  4026. X    printf ("\n");
  4027. X    }
  4028. X
  4029. X    /*
  4030. X     * So you don't get penalized for being "slow" after this.
  4031. X     */
  4032. X    if (charbychar)
  4033. X    slowpoke = SLOWPOKEMAX + 1;
  4034. X
  4035. X    fflush (stdout);
  4036. X}
  4037. X
  4038. Xint
  4039. Xrancomp (elem1, elem2)
  4040. X    int            *elem1, *elem2;
  4041. X{
  4042. Xfloat           a, b;
  4043. X
  4044. X    a = (randomfactor[(*elem1)] + (randomripe[(*elem1)] / (float) RIPECOUNT));
  4045. X    b = (randomfactor[(*elem2)] + (randomripe[(*elem2)] / (float) RIPECOUNT));
  4046. X
  4047. X    if (a == b)
  4048. X    return 0;
  4049. X    else if (a > b)
  4050. X    return -1;
  4051. X    else
  4052. X    return 1;
  4053. X}
  4054. END_OF_FILE
  4055. if test 43613 -ne `wc -c <'morse.c'`; then
  4056.     echo shar: \"'morse.c'\" unpacked with wrong size!
  4057. fi
  4058. # end of 'morse.c'
  4059. fi
  4060. echo shar: End of shell archive.
  4061. exit 0
  4062.